236 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * LASI Device Driver4 *5 * (c) Copyright 1999 Red Hat Software6 * Portions (c) Copyright 1999 The Puffin Group Inc.7 * Portions (c) Copyright 1999 Hewlett-Packard8 *9 * by Alan Cox <alan@redhat.com> and 10 * Alex deVries <alex@onefishtwo.ca>11 */12 13#include <linux/errno.h>14#include <linux/init.h>15#include <linux/interrupt.h>16#include <linux/slab.h>17#include <linux/module.h>18#include <linux/pm.h>19#include <linux/types.h>20#include <linux/reboot.h>21 22#include <asm/io.h>23#include <asm/hardware.h>24#include <asm/led.h>25 26#include "gsc.h"27 28 29#define LASI_VER 0xC008 /* LASI Version */30 31#define LASI_IO_CONF 0x7FFFE /* LASI primary configuration register */32#define LASI_IO_CONF2 0x7FFFF /* LASI secondary configuration register */33 34static void lasi_choose_irq(struct parisc_device *dev, void *ctrl)35{36 int irq;37 38 switch (dev->id.sversion) {39 case 0x74: irq = 7; break; /* Centronics */40 case 0x7B: irq = 13; break; /* Audio */41 case 0x81: irq = 14; break; /* Lasi itself */42 case 0x82: irq = 9; break; /* SCSI */43 case 0x83: irq = 20; break; /* Floppy */44 case 0x84: irq = 26; break; /* PS/2 Keyboard */45 case 0x87: irq = 18; break; /* ISDN */46 case 0x8A: irq = 8; break; /* LAN */47 case 0x8C: irq = 5; break; /* RS232 */48 case 0x8D: irq = (dev->hw_path == 13) ? 16 : 17; break;49 /* Telephone */50 default: return; /* unknown */51 }52 53 gsc_asic_assign_irq(ctrl, irq, &dev->irq);54}55 56static void __init57lasi_init_irq(struct gsc_asic *this_lasi)58{59 unsigned long lasi_base = this_lasi->hpa;60 61 /* Stop LASI barking for a bit */62 gsc_writel(0x00000000, lasi_base+OFFSET_IMR);63 64 /* clear pending interrupts */65 gsc_readl(lasi_base+OFFSET_IRR);66 67 /* We're not really convinced we want to reset the onboard68 * devices. Firmware does it for us...69 */70 71 /* Resets */72 /* gsc_writel(0xFFFFFFFF, lasi_base+0x2000);*/ /* Parallel */73 if(pdc_add_valid(lasi_base+0x4004) == PDC_OK)74 gsc_writel(0xFFFFFFFF, lasi_base+0x4004); /* Audio */75 /* gsc_writel(0xFFFFFFFF, lasi_base+0x5000);*/ /* Serial */ 76 /* gsc_writel(0xFFFFFFFF, lasi_base+0x6000);*/ /* SCSI */77 gsc_writel(0xFFFFFFFF, lasi_base+0x7000); /* LAN */78 gsc_writel(0xFFFFFFFF, lasi_base+0x8000); /* Keyboard */79 gsc_writel(0xFFFFFFFF, lasi_base+0xA000); /* FDC */80 81 /* Ok we hit it on the head with a hammer, our Dog is now82 ** comatose and muzzled. Devices will now unmask LASI83 ** interrupts as they are registered as irq's in the LASI range.84 */85 /* XXX: I thought it was `awks that got `it on the `ead with an86 * `ammer. -- willy87 */88}89 90 91/*92 ** lasi_led_init()93 ** 94 ** lasi_led_init() initializes the LED controller on the LASI.95 **96 ** Since Mirage and Electra machines use a different LED97 ** address register, we need to check for these machines 98 ** explicitly.99 */100 101#ifndef CONFIG_CHASSIS_LCD_LED102 103#define lasi_led_init(x) /* nothing */104 105#else106 107static void __init lasi_led_init(unsigned long lasi_hpa)108{109 unsigned long datareg;110 111 switch (CPU_HVERSION) {112 /* Gecko machines have only one single LED, which can be permanently 113 turned on by writing a zero into the power control register. */ 114 case 0x600: /* Gecko (712/60) */115 case 0x601: /* Gecko (712/80) */116 case 0x602: /* Gecko (712/100) */117 case 0x603: /* Anole 64 (743/64) */118 case 0x604: /* Anole 100 (743/100) */119 case 0x605: /* Gecko (712/120) */120 datareg = lasi_hpa + 0x0000C000;121 gsc_writeb(0, datareg);122 return; /* no need to register the LED interrupt-function */ 123 124 /* Mirage and Electra machines need special offsets */125 case 0x60A: /* Mirage Jr (715/64) */126 case 0x60B: /* Mirage 100 */127 case 0x60C: /* Mirage 100+ */128 case 0x60D: /* Electra 100 */129 case 0x60E: /* Electra 120 */130 datareg = lasi_hpa - 0x00020000;131 break;132 133 default:134 datareg = lasi_hpa + 0x0000C000;135 break;136 }137 138 register_led_driver(DISPLAY_MODEL_LASI, LED_CMD_REG_NONE, datareg);139}140#endif141 142/*143 * lasi_power_off144 *145 * Function for lasi to turn off the power. This is accomplished by setting a146 * 1 to PWR_ON_L in the Power Control Register147 * 148 */149static int lasi_power_off(struct sys_off_data *data)150{151 struct gsc_asic *lasi = data->cb_data;152 153 /* Power down the machine via Power Control Register */154 gsc_writel(0x02, lasi->hpa + 0x0000C000);155 156 /* might not be reached: */157 return NOTIFY_DONE;158}159 160static int __init lasi_init_chip(struct parisc_device *dev)161{162 struct gsc_asic *lasi;163 int ret;164 165 lasi = kzalloc(sizeof(*lasi), GFP_KERNEL);166 if (!lasi)167 return -ENOMEM;168 169 lasi->name = "Lasi";170 lasi->hpa = dev->hpa.start;171 172 /* Check the 4-bit (yes, only 4) version register */173 lasi->version = gsc_readl(lasi->hpa + LASI_VER) & 0xf;174 printk(KERN_INFO "%s version %d at 0x%lx found.\n",175 lasi->name, lasi->version, lasi->hpa);176 177 /* initialize the chassis LEDs really early */ 178 lasi_led_init(lasi->hpa);179 180 /* Stop LASI barking for a bit */181 lasi_init_irq(lasi);182 183 /* the IRQ lasi should use */184 dev->irq = gsc_alloc_irq(&lasi->gsc_irq);185 if (dev->irq < 0) {186 printk(KERN_ERR "%s(): cannot get GSC irq\n",187 __func__);188 kfree(lasi);189 return -EBUSY;190 }191 192 lasi->eim = ((u32) lasi->gsc_irq.txn_addr) | lasi->gsc_irq.txn_data;193 194 ret = request_irq(lasi->gsc_irq.irq, gsc_asic_intr, 0, "lasi", lasi);195 if (ret < 0) {196 kfree(lasi);197 return ret;198 }199 200 /* enable IRQ's for devices below LASI */201 gsc_writel(lasi->eim, lasi->hpa + OFFSET_IAR);202 203 /* Done init'ing, register this driver */204 ret = gsc_common_setup(dev, lasi);205 if (ret) {206 kfree(lasi);207 return ret;208 } 209 210 gsc_fixup_irqs(dev, lasi, lasi_choose_irq);211 212 /* register the LASI power off function */213 register_sys_off_handler(SYS_OFF_MODE_POWER_OFF,214 SYS_OFF_PRIO_DEFAULT, lasi_power_off, lasi);215 216 return ret;217}218 219static struct parisc_device_id lasi_tbl[] __initdata = {220 { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00081 },221 { 0, }222};223MODULE_DEVICE_TABLE(parisc, lasi_tbl);224 225static struct parisc_driver lasi_driver __refdata = {226 .name = "lasi",227 .id_table = lasi_tbl,228 .probe = lasi_init_chip,229};230 231static int __init lasi_init(void)232{233 return register_parisc_driver(&lasi_driver);234}235arch_initcall(lasi_init);236