Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Driver for Feature Integration Technology Inc. (aka Fintek) LPC CIR
0004  *
0005  * Copyright (C) 2011 Jarod Wilson <jarod@redhat.com>
0006  *
0007  * Special thanks to Fintek for providing hardware and spec sheets.
0008  * This driver is based upon the nuvoton, ite and ene drivers for
0009  * similar hardware.
0010  */
0011 
0012 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0013 
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/pnp.h>
0017 #include <linux/io.h>
0018 #include <linux/interrupt.h>
0019 #include <linux/sched.h>
0020 #include <linux/slab.h>
0021 #include <media/rc-core.h>
0022 
0023 #include "fintek-cir.h"
0024 
0025 /* write val to config reg */
0026 static inline void fintek_cr_write(struct fintek_dev *fintek, u8 val, u8 reg)
0027 {
0028     fit_dbg("%s: reg 0x%02x, val 0x%02x  (ip/dp: %02x/%02x)",
0029         __func__, reg, val, fintek->cr_ip, fintek->cr_dp);
0030     outb(reg, fintek->cr_ip);
0031     outb(val, fintek->cr_dp);
0032 }
0033 
0034 /* read val from config reg */
0035 static inline u8 fintek_cr_read(struct fintek_dev *fintek, u8 reg)
0036 {
0037     u8 val;
0038 
0039     outb(reg, fintek->cr_ip);
0040     val = inb(fintek->cr_dp);
0041 
0042     fit_dbg("%s: reg 0x%02x, val 0x%02x  (ip/dp: %02x/%02x)",
0043         __func__, reg, val, fintek->cr_ip, fintek->cr_dp);
0044     return val;
0045 }
0046 
0047 /* update config register bit without changing other bits */
0048 static inline void fintek_set_reg_bit(struct fintek_dev *fintek, u8 val, u8 reg)
0049 {
0050     u8 tmp = fintek_cr_read(fintek, reg) | val;
0051     fintek_cr_write(fintek, tmp, reg);
0052 }
0053 
0054 /* enter config mode */
0055 static inline void fintek_config_mode_enable(struct fintek_dev *fintek)
0056 {
0057     /* Enabling Config Mode explicitly requires writing 2x */
0058     outb(CONFIG_REG_ENABLE, fintek->cr_ip);
0059     outb(CONFIG_REG_ENABLE, fintek->cr_ip);
0060 }
0061 
0062 /* exit config mode */
0063 static inline void fintek_config_mode_disable(struct fintek_dev *fintek)
0064 {
0065     outb(CONFIG_REG_DISABLE, fintek->cr_ip);
0066 }
0067 
0068 /*
0069  * When you want to address a specific logical device, write its logical
0070  * device number to GCR_LOGICAL_DEV_NO
0071  */
0072 static inline void fintek_select_logical_dev(struct fintek_dev *fintek, u8 ldev)
0073 {
0074     fintek_cr_write(fintek, ldev, GCR_LOGICAL_DEV_NO);
0075 }
0076 
0077 /* write val to cir config register */
0078 static inline void fintek_cir_reg_write(struct fintek_dev *fintek, u8 val, u8 offset)
0079 {
0080     outb(val, fintek->cir_addr + offset);
0081 }
0082 
0083 /* read val from cir config register */
0084 static u8 fintek_cir_reg_read(struct fintek_dev *fintek, u8 offset)
0085 {
0086     return inb(fintek->cir_addr + offset);
0087 }
0088 
0089 /* dump current cir register contents */
0090 static void cir_dump_regs(struct fintek_dev *fintek)
0091 {
0092     fintek_config_mode_enable(fintek);
0093     fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
0094 
0095     pr_info("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME);
0096     pr_info(" * CR CIR BASE ADDR: 0x%x\n",
0097         (fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) |
0098         fintek_cr_read(fintek, CIR_CR_BASE_ADDR_LO));
0099     pr_info(" * CR CIR IRQ NUM:   0x%x\n",
0100         fintek_cr_read(fintek, CIR_CR_IRQ_SEL));
0101 
0102     fintek_config_mode_disable(fintek);
0103 
0104     pr_info("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME);
0105     pr_info(" * STATUS:     0x%x\n",
0106         fintek_cir_reg_read(fintek, CIR_STATUS));
0107     pr_info(" * CONTROL:    0x%x\n",
0108         fintek_cir_reg_read(fintek, CIR_CONTROL));
0109     pr_info(" * RX_DATA:    0x%x\n",
0110         fintek_cir_reg_read(fintek, CIR_RX_DATA));
0111     pr_info(" * TX_CONTROL: 0x%x\n",
0112         fintek_cir_reg_read(fintek, CIR_TX_CONTROL));
0113     pr_info(" * TX_DATA:    0x%x\n",
0114         fintek_cir_reg_read(fintek, CIR_TX_DATA));
0115 }
0116 
0117 /* detect hardware features */
0118 static int fintek_hw_detect(struct fintek_dev *fintek)
0119 {
0120     unsigned long flags;
0121     u8 chip_major, chip_minor;
0122     u8 vendor_major, vendor_minor;
0123     u8 portsel, ir_class;
0124     u16 vendor, chip;
0125 
0126     fintek_config_mode_enable(fintek);
0127 
0128     /* Check if we're using config port 0x4e or 0x2e */
0129     portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL);
0130     if (portsel == 0xff) {
0131         fit_pr(KERN_INFO, "first portsel read was bunk, trying alt");
0132         fintek_config_mode_disable(fintek);
0133         fintek->cr_ip = CR_INDEX_PORT2;
0134         fintek->cr_dp = CR_DATA_PORT2;
0135         fintek_config_mode_enable(fintek);
0136         portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL);
0137     }
0138     fit_dbg("portsel reg: 0x%02x", portsel);
0139 
0140     ir_class = fintek_cir_reg_read(fintek, CIR_CR_CLASS);
0141     fit_dbg("ir_class reg: 0x%02x", ir_class);
0142 
0143     switch (ir_class) {
0144     case CLASS_RX_2TX:
0145     case CLASS_RX_1TX:
0146         fintek->hw_tx_capable = true;
0147         break;
0148     case CLASS_RX_ONLY:
0149     default:
0150         fintek->hw_tx_capable = false;
0151         break;
0152     }
0153 
0154     chip_major = fintek_cr_read(fintek, GCR_CHIP_ID_HI);
0155     chip_minor = fintek_cr_read(fintek, GCR_CHIP_ID_LO);
0156     chip  = chip_major << 8 | chip_minor;
0157 
0158     vendor_major = fintek_cr_read(fintek, GCR_VENDOR_ID_HI);
0159     vendor_minor = fintek_cr_read(fintek, GCR_VENDOR_ID_LO);
0160     vendor = vendor_major << 8 | vendor_minor;
0161 
0162     if (vendor != VENDOR_ID_FINTEK)
0163         fit_pr(KERN_WARNING, "Unknown vendor ID: 0x%04x", vendor);
0164     else
0165         fit_dbg("Read Fintek vendor ID from chip");
0166 
0167     fintek_config_mode_disable(fintek);
0168 
0169     spin_lock_irqsave(&fintek->fintek_lock, flags);
0170     fintek->chip_major  = chip_major;
0171     fintek->chip_minor  = chip_minor;
0172     fintek->chip_vendor = vendor;
0173 
0174     /*
0175      * Newer reviews of this chipset uses port 8 instead of 5
0176      */
0177     if ((chip != 0x0408) && (chip != 0x0804))
0178         fintek->logical_dev_cir = LOGICAL_DEV_CIR_REV2;
0179     else
0180         fintek->logical_dev_cir = LOGICAL_DEV_CIR_REV1;
0181 
0182     spin_unlock_irqrestore(&fintek->fintek_lock, flags);
0183 
0184     return 0;
0185 }
0186 
0187 static void fintek_cir_ldev_init(struct fintek_dev *fintek)
0188 {
0189     /* Select CIR logical device and enable */
0190     fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
0191     fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN);
0192 
0193     /* Write allocated CIR address and IRQ information to hardware */
0194     fintek_cr_write(fintek, fintek->cir_addr >> 8, CIR_CR_BASE_ADDR_HI);
0195     fintek_cr_write(fintek, fintek->cir_addr & 0xff, CIR_CR_BASE_ADDR_LO);
0196 
0197     fintek_cr_write(fintek, fintek->cir_irq, CIR_CR_IRQ_SEL);
0198 
0199     fit_dbg("CIR initialized, base io address: 0x%lx, irq: %d (len: %d)",
0200         fintek->cir_addr, fintek->cir_irq, fintek->cir_port_len);
0201 }
0202 
0203 /* enable CIR interrupts */
0204 static void fintek_enable_cir_irq(struct fintek_dev *fintek)
0205 {
0206     fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS);
0207 }
0208 
0209 static void fintek_cir_regs_init(struct fintek_dev *fintek)
0210 {
0211     /* clear any and all stray interrupts */
0212     fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
0213 
0214     /* and finally, enable interrupts */
0215     fintek_enable_cir_irq(fintek);
0216 }
0217 
0218 static void fintek_enable_wake(struct fintek_dev *fintek)
0219 {
0220     fintek_config_mode_enable(fintek);
0221     fintek_select_logical_dev(fintek, LOGICAL_DEV_ACPI);
0222 
0223     /* Allow CIR PME's to wake system */
0224     fintek_set_reg_bit(fintek, ACPI_WAKE_EN_CIR_BIT, LDEV_ACPI_WAKE_EN_REG);
0225     /* Enable CIR PME's */
0226     fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_EN_REG);
0227     /* Clear CIR PME status register */
0228     fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_CLR_REG);
0229     /* Save state */
0230     fintek_set_reg_bit(fintek, ACPI_STATE_CIR_BIT, LDEV_ACPI_STATE_REG);
0231 
0232     fintek_config_mode_disable(fintek);
0233 }
0234 
0235 static int fintek_cmdsize(u8 cmd, u8 subcmd)
0236 {
0237     int datasize = 0;
0238 
0239     switch (cmd) {
0240     case BUF_COMMAND_NULL:
0241         if (subcmd == BUF_HW_CMD_HEADER)
0242             datasize = 1;
0243         break;
0244     case BUF_HW_CMD_HEADER:
0245         if (subcmd == BUF_CMD_G_REVISION)
0246             datasize = 2;
0247         break;
0248     case BUF_COMMAND_HEADER:
0249         switch (subcmd) {
0250         case BUF_CMD_S_CARRIER:
0251         case BUF_CMD_S_TIMEOUT:
0252         case BUF_RSP_PULSE_COUNT:
0253             datasize = 2;
0254             break;
0255         case BUF_CMD_SIG_END:
0256         case BUF_CMD_S_TXMASK:
0257         case BUF_CMD_S_RXSENSOR:
0258             datasize = 1;
0259             break;
0260         }
0261     }
0262 
0263     return datasize;
0264 }
0265 
0266 /* process ir data stored in driver buffer */
0267 static void fintek_process_rx_ir_data(struct fintek_dev *fintek)
0268 {
0269     struct ir_raw_event rawir = {};
0270     u8 sample;
0271     bool event = false;
0272     int i;
0273 
0274     for (i = 0; i < fintek->pkts; i++) {
0275         sample = fintek->buf[i];
0276         switch (fintek->parser_state) {
0277         case CMD_HEADER:
0278             fintek->cmd = sample;
0279             if ((fintek->cmd == BUF_COMMAND_HEADER) ||
0280                 ((fintek->cmd & BUF_COMMAND_MASK) !=
0281                  BUF_PULSE_BIT)) {
0282                 fintek->parser_state = SUBCMD;
0283                 continue;
0284             }
0285             fintek->rem = (fintek->cmd & BUF_LEN_MASK);
0286             fit_dbg("%s: rem: 0x%02x", __func__, fintek->rem);
0287             if (fintek->rem)
0288                 fintek->parser_state = PARSE_IRDATA;
0289             else
0290                 ir_raw_event_overflow(fintek->rdev);
0291             break;
0292         case SUBCMD:
0293             fintek->rem = fintek_cmdsize(fintek->cmd, sample);
0294             fintek->parser_state = CMD_DATA;
0295             break;
0296         case CMD_DATA:
0297             fintek->rem--;
0298             break;
0299         case PARSE_IRDATA:
0300             fintek->rem--;
0301             rawir.pulse = ((sample & BUF_PULSE_BIT) != 0);
0302             rawir.duration = (sample & BUF_SAMPLE_MASK)
0303                       * CIR_SAMPLE_PERIOD;
0304 
0305             fit_dbg("Storing %s with duration %d",
0306                 rawir.pulse ? "pulse" : "space",
0307                 rawir.duration);
0308             if (ir_raw_event_store_with_filter(fintek->rdev,
0309                                     &rawir))
0310                 event = true;
0311             break;
0312         }
0313 
0314         if ((fintek->parser_state != CMD_HEADER) && !fintek->rem)
0315             fintek->parser_state = CMD_HEADER;
0316     }
0317 
0318     fintek->pkts = 0;
0319 
0320     if (event) {
0321         fit_dbg("Calling ir_raw_event_handle");
0322         ir_raw_event_handle(fintek->rdev);
0323     }
0324 }
0325 
0326 /* copy data from hardware rx register into driver buffer */
0327 static void fintek_get_rx_ir_data(struct fintek_dev *fintek, u8 rx_irqs)
0328 {
0329     unsigned long flags;
0330     u8 sample, status;
0331 
0332     spin_lock_irqsave(&fintek->fintek_lock, flags);
0333 
0334     /*
0335      * We must read data from CIR_RX_DATA until the hardware IR buffer
0336      * is empty and clears the RX_TIMEOUT and/or RX_RECEIVE flags in
0337      * the CIR_STATUS register
0338      */
0339     do {
0340         sample = fintek_cir_reg_read(fintek, CIR_RX_DATA);
0341         fit_dbg("%s: sample: 0x%02x", __func__, sample);
0342 
0343         fintek->buf[fintek->pkts] = sample;
0344         fintek->pkts++;
0345 
0346         status = fintek_cir_reg_read(fintek, CIR_STATUS);
0347         if (!(status & CIR_STATUS_IRQ_EN))
0348             break;
0349     } while (status & rx_irqs);
0350 
0351     fintek_process_rx_ir_data(fintek);
0352 
0353     spin_unlock_irqrestore(&fintek->fintek_lock, flags);
0354 }
0355 
0356 static void fintek_cir_log_irqs(u8 status)
0357 {
0358     fit_pr(KERN_INFO, "IRQ 0x%02x:%s%s%s%s%s", status,
0359         status & CIR_STATUS_IRQ_EN  ? " IRQEN"  : "",
0360         status & CIR_STATUS_TX_FINISH   ? " TXF"    : "",
0361         status & CIR_STATUS_TX_UNDERRUN ? " TXU"    : "",
0362         status & CIR_STATUS_RX_TIMEOUT  ? " RXTO"   : "",
0363         status & CIR_STATUS_RX_RECEIVE  ? " RXOK"   : "");
0364 }
0365 
0366 /* interrupt service routine for incoming and outgoing CIR data */
0367 static irqreturn_t fintek_cir_isr(int irq, void *data)
0368 {
0369     struct fintek_dev *fintek = data;
0370     u8 status, rx_irqs;
0371 
0372     fit_dbg_verbose("%s firing", __func__);
0373 
0374     fintek_config_mode_enable(fintek);
0375     fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
0376     fintek_config_mode_disable(fintek);
0377 
0378     /*
0379      * Get IR Status register contents. Write 1 to ack/clear
0380      *
0381      * bit: reg name    - description
0382      *   3: TX_FINISH   - TX is finished
0383      *   2: TX_UNDERRUN - TX underrun
0384      *   1: RX_TIMEOUT  - RX data timeout
0385      *   0: RX_RECEIVE  - RX data received
0386      */
0387     status = fintek_cir_reg_read(fintek, CIR_STATUS);
0388     if (!(status & CIR_STATUS_IRQ_MASK) || status == 0xff) {
0389         fit_dbg_verbose("%s exiting, IRSTS 0x%02x", __func__, status);
0390         fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
0391         return IRQ_RETVAL(IRQ_NONE);
0392     }
0393 
0394     if (debug)
0395         fintek_cir_log_irqs(status);
0396 
0397     rx_irqs = status & (CIR_STATUS_RX_RECEIVE | CIR_STATUS_RX_TIMEOUT);
0398     if (rx_irqs)
0399         fintek_get_rx_ir_data(fintek, rx_irqs);
0400 
0401     /* ack/clear all irq flags we've got */
0402     fintek_cir_reg_write(fintek, status, CIR_STATUS);
0403 
0404     fit_dbg_verbose("%s done", __func__);
0405     return IRQ_RETVAL(IRQ_HANDLED);
0406 }
0407 
0408 static void fintek_enable_cir(struct fintek_dev *fintek)
0409 {
0410     /* set IRQ enabled */
0411     fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS);
0412 
0413     fintek_config_mode_enable(fintek);
0414 
0415     /* enable the CIR logical device */
0416     fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
0417     fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN);
0418 
0419     fintek_config_mode_disable(fintek);
0420 
0421     /* clear all pending interrupts */
0422     fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
0423 
0424     /* enable interrupts */
0425     fintek_enable_cir_irq(fintek);
0426 }
0427 
0428 static void fintek_disable_cir(struct fintek_dev *fintek)
0429 {
0430     fintek_config_mode_enable(fintek);
0431 
0432     /* disable the CIR logical device */
0433     fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
0434     fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN);
0435 
0436     fintek_config_mode_disable(fintek);
0437 }
0438 
0439 static int fintek_open(struct rc_dev *dev)
0440 {
0441     struct fintek_dev *fintek = dev->priv;
0442     unsigned long flags;
0443 
0444     spin_lock_irqsave(&fintek->fintek_lock, flags);
0445     fintek_enable_cir(fintek);
0446     spin_unlock_irqrestore(&fintek->fintek_lock, flags);
0447 
0448     return 0;
0449 }
0450 
0451 static void fintek_close(struct rc_dev *dev)
0452 {
0453     struct fintek_dev *fintek = dev->priv;
0454     unsigned long flags;
0455 
0456     spin_lock_irqsave(&fintek->fintek_lock, flags);
0457     fintek_disable_cir(fintek);
0458     spin_unlock_irqrestore(&fintek->fintek_lock, flags);
0459 }
0460 
0461 /* Allocate memory, probe hardware, and initialize everything */
0462 static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
0463 {
0464     struct fintek_dev *fintek;
0465     struct rc_dev *rdev;
0466     int ret = -ENOMEM;
0467 
0468     fintek = kzalloc(sizeof(struct fintek_dev), GFP_KERNEL);
0469     if (!fintek)
0470         return ret;
0471 
0472     /* input device for IR remote (and tx) */
0473     rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
0474     if (!rdev)
0475         goto exit_free_dev_rdev;
0476 
0477     ret = -ENODEV;
0478     /* validate pnp resources */
0479     if (!pnp_port_valid(pdev, 0)) {
0480         dev_err(&pdev->dev, "IR PNP Port not valid!\n");
0481         goto exit_free_dev_rdev;
0482     }
0483 
0484     if (!pnp_irq_valid(pdev, 0)) {
0485         dev_err(&pdev->dev, "IR PNP IRQ not valid!\n");
0486         goto exit_free_dev_rdev;
0487     }
0488 
0489     fintek->cir_addr = pnp_port_start(pdev, 0);
0490     fintek->cir_irq  = pnp_irq(pdev, 0);
0491     fintek->cir_port_len = pnp_port_len(pdev, 0);
0492 
0493     fintek->cr_ip = CR_INDEX_PORT;
0494     fintek->cr_dp = CR_DATA_PORT;
0495 
0496     spin_lock_init(&fintek->fintek_lock);
0497 
0498     pnp_set_drvdata(pdev, fintek);
0499     fintek->pdev = pdev;
0500 
0501     ret = fintek_hw_detect(fintek);
0502     if (ret)
0503         goto exit_free_dev_rdev;
0504 
0505     /* Initialize CIR & CIR Wake Logical Devices */
0506     fintek_config_mode_enable(fintek);
0507     fintek_cir_ldev_init(fintek);
0508     fintek_config_mode_disable(fintek);
0509 
0510     /* Initialize CIR & CIR Wake Config Registers */
0511     fintek_cir_regs_init(fintek);
0512 
0513     /* Set up the rc device */
0514     rdev->priv = fintek;
0515     rdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
0516     rdev->open = fintek_open;
0517     rdev->close = fintek_close;
0518     rdev->device_name = FINTEK_DESCRIPTION;
0519     rdev->input_phys = "fintek/cir0";
0520     rdev->input_id.bustype = BUS_HOST;
0521     rdev->input_id.vendor = VENDOR_ID_FINTEK;
0522     rdev->input_id.product = fintek->chip_major;
0523     rdev->input_id.version = fintek->chip_minor;
0524     rdev->dev.parent = &pdev->dev;
0525     rdev->driver_name = FINTEK_DRIVER_NAME;
0526     rdev->map_name = RC_MAP_RC6_MCE;
0527     rdev->timeout = 1000;
0528     /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */
0529     rdev->rx_resolution = CIR_SAMPLE_PERIOD;
0530 
0531     fintek->rdev = rdev;
0532 
0533     ret = -EBUSY;
0534     /* now claim resources */
0535     if (!request_region(fintek->cir_addr,
0536                 fintek->cir_port_len, FINTEK_DRIVER_NAME))
0537         goto exit_free_dev_rdev;
0538 
0539     if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED,
0540             FINTEK_DRIVER_NAME, (void *)fintek))
0541         goto exit_free_cir_addr;
0542 
0543     ret = rc_register_device(rdev);
0544     if (ret)
0545         goto exit_free_irq;
0546 
0547     device_init_wakeup(&pdev->dev, true);
0548 
0549     fit_pr(KERN_NOTICE, "driver has been successfully loaded\n");
0550     if (debug)
0551         cir_dump_regs(fintek);
0552 
0553     return 0;
0554 
0555 exit_free_irq:
0556     free_irq(fintek->cir_irq, fintek);
0557 exit_free_cir_addr:
0558     release_region(fintek->cir_addr, fintek->cir_port_len);
0559 exit_free_dev_rdev:
0560     rc_free_device(rdev);
0561     kfree(fintek);
0562 
0563     return ret;
0564 }
0565 
0566 static void fintek_remove(struct pnp_dev *pdev)
0567 {
0568     struct fintek_dev *fintek = pnp_get_drvdata(pdev);
0569     unsigned long flags;
0570 
0571     spin_lock_irqsave(&fintek->fintek_lock, flags);
0572     /* disable CIR */
0573     fintek_disable_cir(fintek);
0574     fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
0575     /* enable CIR Wake (for IR power-on) */
0576     fintek_enable_wake(fintek);
0577     spin_unlock_irqrestore(&fintek->fintek_lock, flags);
0578 
0579     /* free resources */
0580     free_irq(fintek->cir_irq, fintek);
0581     release_region(fintek->cir_addr, fintek->cir_port_len);
0582 
0583     rc_unregister_device(fintek->rdev);
0584 
0585     kfree(fintek);
0586 }
0587 
0588 static int fintek_suspend(struct pnp_dev *pdev, pm_message_t state)
0589 {
0590     struct fintek_dev *fintek = pnp_get_drvdata(pdev);
0591     unsigned long flags;
0592 
0593     fit_dbg("%s called", __func__);
0594 
0595     spin_lock_irqsave(&fintek->fintek_lock, flags);
0596 
0597     /* disable all CIR interrupts */
0598     fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
0599 
0600     spin_unlock_irqrestore(&fintek->fintek_lock, flags);
0601 
0602     fintek_config_mode_enable(fintek);
0603 
0604     /* disable cir logical dev */
0605     fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
0606     fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN);
0607 
0608     fintek_config_mode_disable(fintek);
0609 
0610     /* make sure wake is enabled */
0611     fintek_enable_wake(fintek);
0612 
0613     return 0;
0614 }
0615 
0616 static int fintek_resume(struct pnp_dev *pdev)
0617 {
0618     struct fintek_dev *fintek = pnp_get_drvdata(pdev);
0619 
0620     fit_dbg("%s called", __func__);
0621 
0622     /* open interrupt */
0623     fintek_enable_cir_irq(fintek);
0624 
0625     /* Enable CIR logical device */
0626     fintek_config_mode_enable(fintek);
0627     fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
0628     fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN);
0629 
0630     fintek_config_mode_disable(fintek);
0631 
0632     fintek_cir_regs_init(fintek);
0633 
0634     return 0;
0635 }
0636 
0637 static void fintek_shutdown(struct pnp_dev *pdev)
0638 {
0639     struct fintek_dev *fintek = pnp_get_drvdata(pdev);
0640     fintek_enable_wake(fintek);
0641 }
0642 
0643 static const struct pnp_device_id fintek_ids[] = {
0644     { "FIT0002", 0 },   /* CIR */
0645     { "", 0 },
0646 };
0647 
0648 static struct pnp_driver fintek_driver = {
0649     .name       = FINTEK_DRIVER_NAME,
0650     .id_table   = fintek_ids,
0651     .flags      = PNP_DRIVER_RES_DO_NOT_CHANGE,
0652     .probe      = fintek_probe,
0653     .remove     = fintek_remove,
0654     .suspend    = fintek_suspend,
0655     .resume     = fintek_resume,
0656     .shutdown   = fintek_shutdown,
0657 };
0658 
0659 module_param(debug, int, S_IRUGO | S_IWUSR);
0660 MODULE_PARM_DESC(debug, "Enable debugging output");
0661 
0662 MODULE_DEVICE_TABLE(pnp, fintek_ids);
0663 MODULE_DESCRIPTION(FINTEK_DESCRIPTION " driver");
0664 
0665 MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
0666 MODULE_LICENSE("GPL");
0667 
0668 module_pnp_driver(fintek_driver);