19bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* 29bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * Driver for Feature Integration Technology Inc. (aka Fintek) LPC CIR 39bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * 49bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * Copyright (C) 2011 Jarod Wilson <jarod@redhat.com> 59bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * 69bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * Special thanks to Fintek for providing hardware and spec sheets. 79bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * This driver is based upon the nuvoton, ite and ene drivers for 89bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * similar hardware. 99bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * 109bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * This program is free software; you can redistribute it and/or 119bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * modify it under the terms of the GNU General Public License as 129bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * published by the Free Software Foundation; either version 2 of the 139bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * License, or (at your option) any later version. 149bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * 159bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * This program is distributed in the hope that it will be useful, but 169bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * WITHOUT ANY WARRANTY; without even the implied warranty of 179bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 189bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * General Public License for more details. 199bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * 209bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * You should have received a copy of the GNU General Public License 219bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * along with this program; if not, write to the Free Software 229bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 239bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * USA 249bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson */ 259bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 269bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson#include <linux/kernel.h> 279bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson#include <linux/module.h> 289bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson#include <linux/pnp.h> 299bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson#include <linux/io.h> 309bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson#include <linux/interrupt.h> 319bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson#include <linux/sched.h> 329bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson#include <linux/slab.h> 339bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson#include <media/rc-core.h> 349bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson#include <linux/pci_ids.h> 359bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 369bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson#include "fintek-cir.h" 379bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 389bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* write val to config reg */ 399bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic inline void fintek_cr_write(struct fintek_dev *fintek, u8 val, u8 reg) 409bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 419bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg("%s: reg 0x%02x, val 0x%02x (ip/dp: %02x/%02x)", 429bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson __func__, reg, val, fintek->cr_ip, fintek->cr_dp); 439bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson outb(reg, fintek->cr_ip); 449bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson outb(val, fintek->cr_dp); 459bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 469bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 479bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* read val from config reg */ 489bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic inline u8 fintek_cr_read(struct fintek_dev *fintek, u8 reg) 499bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 509bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson u8 val; 519bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 529bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson outb(reg, fintek->cr_ip); 539bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson val = inb(fintek->cr_dp); 549bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 559bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg("%s: reg 0x%02x, val 0x%02x (ip/dp: %02x/%02x)", 569bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson __func__, reg, val, fintek->cr_ip, fintek->cr_dp); 579bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson return val; 589bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 599bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 609bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* update config register bit without changing other bits */ 619bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic inline void fintek_set_reg_bit(struct fintek_dev *fintek, u8 val, u8 reg) 629bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 639bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson u8 tmp = fintek_cr_read(fintek, reg) | val; 649bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cr_write(fintek, tmp, reg); 659bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 669bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 679bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* clear config register bit without changing other bits */ 689bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic inline void fintek_clear_reg_bit(struct fintek_dev *fintek, u8 val, u8 reg) 699bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 709bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson u8 tmp = fintek_cr_read(fintek, reg) & ~val; 719bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cr_write(fintek, tmp, reg); 729bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 739bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 749bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* enter config mode */ 759bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic inline void fintek_config_mode_enable(struct fintek_dev *fintek) 769bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 779bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* Enabling Config Mode explicitly requires writing 2x */ 789bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson outb(CONFIG_REG_ENABLE, fintek->cr_ip); 799bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson outb(CONFIG_REG_ENABLE, fintek->cr_ip); 809bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 819bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 829bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* exit config mode */ 839bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic inline void fintek_config_mode_disable(struct fintek_dev *fintek) 849bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 859bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson outb(CONFIG_REG_DISABLE, fintek->cr_ip); 869bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 879bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 889bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* 899bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * When you want to address a specific logical device, write its logical 909bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * device number to GCR_LOGICAL_DEV_NO 919bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson */ 929bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic inline void fintek_select_logical_dev(struct fintek_dev *fintek, u8 ldev) 939bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 949bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cr_write(fintek, ldev, GCR_LOGICAL_DEV_NO); 959bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 969bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 979bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* write val to cir config register */ 989bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic inline void fintek_cir_reg_write(struct fintek_dev *fintek, u8 val, u8 offset) 999bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 1009bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson outb(val, fintek->cir_addr + offset); 1019bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 1029bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1039bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* read val from cir config register */ 1049bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic u8 fintek_cir_reg_read(struct fintek_dev *fintek, u8 offset) 1059bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 1069bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson u8 val; 1079bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1089bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson val = inb(fintek->cir_addr + offset); 1099bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1109bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson return val; 1119bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 1129bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1139bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson#define pr_reg(text, ...) \ 1149bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__) 1159bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1169bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* dump current cir register contents */ 1179bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic void cir_dump_regs(struct fintek_dev *fintek) 1189bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 1199bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_enable(fintek); 1209bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); 1219bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1229bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson pr_reg("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME); 1239bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson pr_reg(" * CR CIR BASE ADDR: 0x%x\n", 1249bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson (fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) | 1259bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cr_read(fintek, CIR_CR_BASE_ADDR_LO)); 1269bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson pr_reg(" * CR CIR IRQ NUM: 0x%x\n", 1279bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cr_read(fintek, CIR_CR_IRQ_SEL)); 1289bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1299bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_disable(fintek); 1309bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1319bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson pr_reg("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME); 1329bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson pr_reg(" * STATUS: 0x%x\n", fintek_cir_reg_read(fintek, CIR_STATUS)); 1339bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson pr_reg(" * CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_CONTROL)); 1349bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson pr_reg(" * RX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_RX_DATA)); 1359bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson pr_reg(" * TX_CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_CONTROL)); 1369bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson pr_reg(" * TX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_DATA)); 1379bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 1389bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1399bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* detect hardware features */ 1409bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic int fintek_hw_detect(struct fintek_dev *fintek) 1419bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 1429bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson unsigned long flags; 1439bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson u8 chip_major, chip_minor; 1449bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson u8 vendor_major, vendor_minor; 1459bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson u8 portsel, ir_class; 1469bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson u16 vendor; 1479bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson int ret = 0; 1489bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1499bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_enable(fintek); 1509bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1519bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* Check if we're using config port 0x4e or 0x2e */ 1529bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL); 1539bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (portsel == 0xff) { 1549bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_pr(KERN_INFO, "first portsel read was bunk, trying alt"); 1559bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_disable(fintek); 1569bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->cr_ip = CR_INDEX_PORT2; 1579bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->cr_dp = CR_DATA_PORT2; 1589bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_enable(fintek); 1599bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL); 1609bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson } 1619bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg("portsel reg: 0x%02x", portsel); 1629bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1639bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson ir_class = fintek_cir_reg_read(fintek, CIR_CR_CLASS); 1649bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg("ir_class reg: 0x%02x", ir_class); 1659bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1669bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson switch (ir_class) { 1679bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case CLASS_RX_2TX: 1689bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case CLASS_RX_1TX: 1699bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->hw_tx_capable = true; 1709bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson break; 1719bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case CLASS_RX_ONLY: 1729bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson default: 1739bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->hw_tx_capable = false; 1749bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson break; 1759bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson } 1769bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1779bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson chip_major = fintek_cr_read(fintek, GCR_CHIP_ID_HI); 1789bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson chip_minor = fintek_cr_read(fintek, GCR_CHIP_ID_LO); 1799bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1809bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson vendor_major = fintek_cr_read(fintek, GCR_VENDOR_ID_HI); 1819bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson vendor_minor = fintek_cr_read(fintek, GCR_VENDOR_ID_LO); 1829bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson vendor = vendor_major << 8 | vendor_minor; 1839bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1849bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (vendor != VENDOR_ID_FINTEK) 1859bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_pr(KERN_WARNING, "Unknown vendor ID: 0x%04x", vendor); 1869bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson else 1879bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg("Read Fintek vendor ID from chip"); 1889bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1899bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_disable(fintek); 1909bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1919bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson spin_lock_irqsave(&fintek->fintek_lock, flags); 1929bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->chip_major = chip_major; 1939bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->chip_minor = chip_minor; 1949bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->chip_vendor = vendor; 1959bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson spin_unlock_irqrestore(&fintek->fintek_lock, flags); 1969bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 1979bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson return ret; 1989bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 1999bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2009bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic void fintek_cir_ldev_init(struct fintek_dev *fintek) 2019bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 2029bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* Select CIR logical device and enable */ 2039bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); 2049bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); 2059bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2069bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* Write allocated CIR address and IRQ information to hardware */ 2079bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cr_write(fintek, fintek->cir_addr >> 8, CIR_CR_BASE_ADDR_HI); 2089bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cr_write(fintek, fintek->cir_addr & 0xff, CIR_CR_BASE_ADDR_LO); 2099bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2109bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cr_write(fintek, fintek->cir_irq, CIR_CR_IRQ_SEL); 2119bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2129bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg("CIR initialized, base io address: 0x%lx, irq: %d (len: %d)", 2139bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->cir_addr, fintek->cir_irq, fintek->cir_port_len); 2149bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 2159bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2169bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* enable CIR interrupts */ 2179bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic void fintek_enable_cir_irq(struct fintek_dev *fintek) 2189bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 2199bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS); 2209bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 2219bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2229bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic void fintek_cir_regs_init(struct fintek_dev *fintek) 2239bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 2249bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* clear any and all stray interrupts */ 2259bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); 2269bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2279bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* and finally, enable interrupts */ 2289bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_enable_cir_irq(fintek); 2299bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 2309bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2319bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic void fintek_enable_wake(struct fintek_dev *fintek) 2329bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 2339bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_enable(fintek); 2349bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_select_logical_dev(fintek, LOGICAL_DEV_ACPI); 2359bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2369bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* Allow CIR PME's to wake system */ 2379bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_set_reg_bit(fintek, ACPI_WAKE_EN_CIR_BIT, LDEV_ACPI_WAKE_EN_REG); 2389bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* Enable CIR PME's */ 2399bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_EN_REG); 2409bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* Clear CIR PME status register */ 2419bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_CLR_REG); 2429bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* Save state */ 2439bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_set_reg_bit(fintek, ACPI_STATE_CIR_BIT, LDEV_ACPI_STATE_REG); 2449bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2459bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_disable(fintek); 2469bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 2479bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2489bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic int fintek_cmdsize(u8 cmd, u8 subcmd) 2499bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 2509bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson int datasize = 0; 2519bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2529bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson switch (cmd) { 2539bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case BUF_COMMAND_NULL: 2549bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (subcmd == BUF_HW_CMD_HEADER) 2559bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson datasize = 1; 2569bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson break; 2579bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case BUF_HW_CMD_HEADER: 2589bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (subcmd == BUF_CMD_G_REVISION) 2599bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson datasize = 2; 2609bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson break; 2619bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case BUF_COMMAND_HEADER: 2629bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson switch (subcmd) { 2639bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case BUF_CMD_S_CARRIER: 2649bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case BUF_CMD_S_TIMEOUT: 2659bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case BUF_RSP_PULSE_COUNT: 2669bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson datasize = 2; 2679bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson break; 2689bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case BUF_CMD_SIG_END: 2699bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case BUF_CMD_S_TXMASK: 2709bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case BUF_CMD_S_RXSENSOR: 2719bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson datasize = 1; 2729bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson break; 2739bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson } 2749bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson } 2759bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2769bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson return datasize; 2779bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 2789bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2799bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* process ir data stored in driver buffer */ 2809bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic void fintek_process_rx_ir_data(struct fintek_dev *fintek) 2819bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 2829bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson DEFINE_IR_RAW_EVENT(rawir); 2839bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson u8 sample; 2849bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson int i; 2859bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 2869bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson for (i = 0; i < fintek->pkts; i++) { 2879bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson sample = fintek->buf[i]; 2889bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson switch (fintek->parser_state) { 2899bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case CMD_HEADER: 2909bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->cmd = sample; 2919bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if ((fintek->cmd == BUF_COMMAND_HEADER) || 2929bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson ((fintek->cmd & BUF_COMMAND_MASK) != 2939bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson BUF_PULSE_BIT)) { 2949bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->parser_state = SUBCMD; 2959bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson continue; 2969bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson } 2979bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->rem = (fintek->cmd & BUF_LEN_MASK); 2989bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg("%s: rem: 0x%02x", __func__, fintek->rem); 2999bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (fintek->rem) 3009bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->parser_state = PARSE_IRDATA; 3019bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson else 3029bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson ir_raw_event_reset(fintek->rdev); 3039bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson break; 3049bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case SUBCMD: 3059bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->rem = fintek_cmdsize(fintek->cmd, sample); 3069bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->parser_state = CMD_DATA; 3079bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson break; 3089bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case CMD_DATA: 3099bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->rem--; 3109bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson break; 3119bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson case PARSE_IRDATA: 3129bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->rem--; 3139bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson init_ir_raw_event(&rawir); 3149bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rawir.pulse = ((sample & BUF_PULSE_BIT) != 0); 3159bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rawir.duration = US_TO_NS((sample & BUF_SAMPLE_MASK) 3169bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * CIR_SAMPLE_PERIOD); 3179bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3189bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg("Storing %s with duration %d", 3199bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rawir.pulse ? "pulse" : "space", 3209bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rawir.duration); 3219bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson ir_raw_event_store_with_filter(fintek->rdev, &rawir); 3229bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson break; 3239bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson } 3249bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3259bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if ((fintek->parser_state != CMD_HEADER) && !fintek->rem) 3269bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->parser_state = CMD_HEADER; 3279bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson } 3289bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3299bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->pkts = 0; 3309bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3319bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg("Calling ir_raw_event_handle"); 3329bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson ir_raw_event_handle(fintek->rdev); 3339bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 3349bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3359bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* copy data from hardware rx register into driver buffer */ 3369bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic void fintek_get_rx_ir_data(struct fintek_dev *fintek, u8 rx_irqs) 3379bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 3389bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson unsigned long flags; 3399bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson u8 sample, status; 3409bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3419bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson spin_lock_irqsave(&fintek->fintek_lock, flags); 3429bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3439bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* 3449bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * We must read data from CIR_RX_DATA until the hardware IR buffer 3459bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * is empty and clears the RX_TIMEOUT and/or RX_RECEIVE flags in 3469bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * the CIR_STATUS register 3479bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson */ 3489bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson do { 3499bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson sample = fintek_cir_reg_read(fintek, CIR_RX_DATA); 3509bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg("%s: sample: 0x%02x", __func__, sample); 3519bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3529bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->buf[fintek->pkts] = sample; 3539bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->pkts++; 3549bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3559bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson status = fintek_cir_reg_read(fintek, CIR_STATUS); 3569bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (!(status & CIR_STATUS_IRQ_EN)) 3579bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson break; 3589bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson } while (status & rx_irqs); 3599bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3609bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_process_rx_ir_data(fintek); 3619bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3629bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson spin_unlock_irqrestore(&fintek->fintek_lock, flags); 3639bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 3649bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3659bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic void fintek_cir_log_irqs(u8 status) 3669bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 3679bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_pr(KERN_INFO, "IRQ 0x%02x:%s%s%s%s%s", status, 3689bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson status & CIR_STATUS_IRQ_EN ? " IRQEN" : "", 3699bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson status & CIR_STATUS_TX_FINISH ? " TXF" : "", 3709bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson status & CIR_STATUS_TX_UNDERRUN ? " TXU" : "", 3719bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson status & CIR_STATUS_RX_TIMEOUT ? " RXTO" : "", 3729bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson status & CIR_STATUS_RX_RECEIVE ? " RXOK" : ""); 3739bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 3749bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3759bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* interrupt service routine for incoming and outgoing CIR data */ 3769bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic irqreturn_t fintek_cir_isr(int irq, void *data) 3779bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 3789bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson struct fintek_dev *fintek = data; 3799bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson u8 status, rx_irqs; 3809bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3819bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg_verbose("%s firing", __func__); 3829bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3839bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_enable(fintek); 3849bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); 3859bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_disable(fintek); 3869bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 3879bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* 3889bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * Get IR Status register contents. Write 1 to ack/clear 3899bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * 3909bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * bit: reg name - description 3919bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * 3: TX_FINISH - TX is finished 3929bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * 2: TX_UNDERRUN - TX underrun 3939bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * 1: RX_TIMEOUT - RX data timeout 3949bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson * 0: RX_RECEIVE - RX data received 3959bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson */ 3969bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson status = fintek_cir_reg_read(fintek, CIR_STATUS); 3979bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (!(status & CIR_STATUS_IRQ_MASK) || status == 0xff) { 3989bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg_verbose("%s exiting, IRSTS 0x%02x", __func__, status); 3999bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); 4009bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson return IRQ_RETVAL(IRQ_NONE); 4019bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson } 4029bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4039bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (debug) 4049bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cir_log_irqs(status); 4059bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4069bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rx_irqs = status & (CIR_STATUS_RX_RECEIVE | CIR_STATUS_RX_TIMEOUT); 4079bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (rx_irqs) 4089bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_get_rx_ir_data(fintek, rx_irqs); 4099bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4109bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* ack/clear all irq flags we've got */ 4119bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cir_reg_write(fintek, status, CIR_STATUS); 4129bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4139bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg_verbose("%s done", __func__); 4149bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson return IRQ_RETVAL(IRQ_HANDLED); 4159bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 4169bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4179bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic void fintek_enable_cir(struct fintek_dev *fintek) 4189bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 4199bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* set IRQ enabled */ 4209bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS); 4219bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4229bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_enable(fintek); 4239bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4249bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* enable the CIR logical device */ 4259bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); 4269bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); 4279bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4289bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_disable(fintek); 4299bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4309bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* clear all pending interrupts */ 4319bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); 4329bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4339bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* enable interrupts */ 4349bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_enable_cir_irq(fintek); 4359bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 4369bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4379bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic void fintek_disable_cir(struct fintek_dev *fintek) 4389bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 4399bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_enable(fintek); 4409bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4419bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* disable the CIR logical device */ 4429bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); 4439bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN); 4449bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4459bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_disable(fintek); 4469bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 4479bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4489bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic int fintek_open(struct rc_dev *dev) 4499bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 4509bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson struct fintek_dev *fintek = dev->priv; 4519bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson unsigned long flags; 4529bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4539bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson spin_lock_irqsave(&fintek->fintek_lock, flags); 4549bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_enable_cir(fintek); 4559bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson spin_unlock_irqrestore(&fintek->fintek_lock, flags); 4569bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4579bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson return 0; 4589bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 4599bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4609bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic void fintek_close(struct rc_dev *dev) 4619bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 4629bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson struct fintek_dev *fintek = dev->priv; 4639bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson unsigned long flags; 4649bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4659bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson spin_lock_irqsave(&fintek->fintek_lock, flags); 4669bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_disable_cir(fintek); 4679bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson spin_unlock_irqrestore(&fintek->fintek_lock, flags); 4689bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 4699bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4709bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson/* Allocate memory, probe hardware, and initialize everything */ 4719bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) 4729bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 4739bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson struct fintek_dev *fintek; 4749bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson struct rc_dev *rdev; 4759bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson int ret = -ENOMEM; 4769bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4779bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek = kzalloc(sizeof(struct fintek_dev), GFP_KERNEL); 4789bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (!fintek) 4799bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson return ret; 4809bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4819bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* input device for IR remote (and tx) */ 4829bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev = rc_allocate_device(); 4839bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (!rdev) 4849bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson goto failure; 4859bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4869bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson ret = -ENODEV; 4879bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* validate pnp resources */ 4889bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (!pnp_port_valid(pdev, 0)) { 4899bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson dev_err(&pdev->dev, "IR PNP Port not valid!\n"); 4909bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson goto failure; 4919bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson } 4929bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4939bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (!pnp_irq_valid(pdev, 0)) { 4949bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson dev_err(&pdev->dev, "IR PNP IRQ not valid!\n"); 4959bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson goto failure; 4969bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson } 4979bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 4989bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->cir_addr = pnp_port_start(pdev, 0); 4999bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->cir_irq = pnp_irq(pdev, 0); 5009bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->cir_port_len = pnp_port_len(pdev, 0); 5019bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5029bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->cr_ip = CR_INDEX_PORT; 5039bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->cr_dp = CR_DATA_PORT; 5049bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5059bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson spin_lock_init(&fintek->fintek_lock); 5069bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5079bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson ret = -EBUSY; 5089bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* now claim resources */ 5099bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (!request_region(fintek->cir_addr, 5109bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->cir_port_len, FINTEK_DRIVER_NAME)) 5119bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson goto failure; 5129bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5139bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED, 5149bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson FINTEK_DRIVER_NAME, (void *)fintek)) 5159bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson goto failure; 5169bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5179bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson pnp_set_drvdata(pdev, fintek); 5189bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->pdev = pdev; 5199bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5209bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson ret = fintek_hw_detect(fintek); 5219bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (ret) 5229bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson goto failure; 5239bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5249bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* Initialize CIR & CIR Wake Logical Devices */ 5259bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_enable(fintek); 5269bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cir_ldev_init(fintek); 5279bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_disable(fintek); 5289bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5299bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* Initialize CIR & CIR Wake Config Registers */ 5309bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cir_regs_init(fintek); 5319bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5329bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* Set up the rc device */ 5339bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->priv = fintek; 5349bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->driver_type = RC_DRIVER_IR_RAW; 5359bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->allowed_protos = RC_TYPE_ALL; 5369bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->open = fintek_open; 5379bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->close = fintek_close; 5389bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->input_name = FINTEK_DESCRIPTION; 5399bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->input_phys = "fintek/cir0"; 5409bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->input_id.bustype = BUS_HOST; 5419bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->input_id.vendor = VENDOR_ID_FINTEK; 5429bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->input_id.product = fintek->chip_major; 5439bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->input_id.version = fintek->chip_minor; 5449bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->dev.parent = &pdev->dev; 5459bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->driver_name = FINTEK_DRIVER_NAME; 5469bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->map_name = RC_MAP_RC6_MCE; 5479bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->timeout = US_TO_NS(1000); 5489bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ 5499bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); 5509bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5519bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson ret = rc_register_device(rdev); 5529bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (ret) 5539bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson goto failure; 5549bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5559bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson device_init_wakeup(&pdev->dev, true); 5569bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek->rdev = rdev; 5579bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_pr(KERN_NOTICE, "driver has been successfully loaded\n"); 5589bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (debug) 5599bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson cir_dump_regs(fintek); 5609bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5619bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson return 0; 5629bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5639bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonfailure: 5649bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (fintek->cir_irq) 5659bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson free_irq(fintek->cir_irq, fintek); 5669bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson if (fintek->cir_addr) 5679bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson release_region(fintek->cir_addr, fintek->cir_port_len); 5689bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5699bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rc_free_device(rdev); 5709bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson kfree(fintek); 5719bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5729bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson return ret; 5739bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 5749bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5759bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic void __devexit fintek_remove(struct pnp_dev *pdev) 5769bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 5779bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson struct fintek_dev *fintek = pnp_get_drvdata(pdev); 5789bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson unsigned long flags; 5799bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5809bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson spin_lock_irqsave(&fintek->fintek_lock, flags); 5819bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* disable CIR */ 5829bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_disable_cir(fintek); 5839bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); 5849bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* enable CIR Wake (for IR power-on) */ 5859bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_enable_wake(fintek); 5869bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson spin_unlock_irqrestore(&fintek->fintek_lock, flags); 5879bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5889bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* free resources */ 5899bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson free_irq(fintek->cir_irq, fintek); 5909bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson release_region(fintek->cir_addr, fintek->cir_port_len); 5919bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5929bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson rc_unregister_device(fintek->rdev); 5939bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5949bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson kfree(fintek); 5959bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 5969bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 5979bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic int fintek_suspend(struct pnp_dev *pdev, pm_message_t state) 5989bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 5999bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson struct fintek_dev *fintek = pnp_get_drvdata(pdev); 6000ae90252d0b28265bc16cf272e72d62281f7baf1Jarod Wilson unsigned long flags; 6019bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6029bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg("%s called", __func__); 6039bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6040ae90252d0b28265bc16cf272e72d62281f7baf1Jarod Wilson spin_lock_irqsave(&fintek->fintek_lock, flags); 6050ae90252d0b28265bc16cf272e72d62281f7baf1Jarod Wilson 6069bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* disable all CIR interrupts */ 6079bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); 6089bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6090ae90252d0b28265bc16cf272e72d62281f7baf1Jarod Wilson spin_unlock_irqrestore(&fintek->fintek_lock, flags); 6100ae90252d0b28265bc16cf272e72d62281f7baf1Jarod Wilson 6119bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_enable(fintek); 6129bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6139bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* disable cir logical dev */ 6149bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); 6159bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN); 6169bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6179bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_disable(fintek); 6189bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6199bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* make sure wake is enabled */ 6209bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_enable_wake(fintek); 6219bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6229bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson return 0; 6239bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 6249bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6259bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic int fintek_resume(struct pnp_dev *pdev) 6269bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 6279bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson int ret = 0; 6289bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson struct fintek_dev *fintek = pnp_get_drvdata(pdev); 6299bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6309bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fit_dbg("%s called", __func__); 6319bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6329bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* open interrupt */ 6339bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_enable_cir_irq(fintek); 6349bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6359bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson /* Enable CIR logical device */ 6369bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_enable(fintek); 6379bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); 6389bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); 6399bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6409bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_config_mode_disable(fintek); 6419bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6429bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_cir_regs_init(fintek); 6439bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6449bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson return ret; 6459bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 6469bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6479bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic void fintek_shutdown(struct pnp_dev *pdev) 6489bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 6499bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson struct fintek_dev *fintek = pnp_get_drvdata(pdev); 6509bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson fintek_enable_wake(fintek); 6519bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 6529bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6539bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic const struct pnp_device_id fintek_ids[] = { 6549bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson { "FIT0002", 0 }, /* CIR */ 6559bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson { "", 0 }, 6569bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson}; 6579bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6589bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonstatic struct pnp_driver fintek_driver = { 6599bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson .name = FINTEK_DRIVER_NAME, 6609bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson .id_table = fintek_ids, 6619bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, 6629bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson .probe = fintek_probe, 6639bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson .remove = __devexit_p(fintek_remove), 6649bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson .suspend = fintek_suspend, 6659bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson .resume = fintek_resume, 6669bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson .shutdown = fintek_shutdown, 6679bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson}; 6689bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6699bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonint fintek_init(void) 6709bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 6719bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson return pnp_register_driver(&fintek_driver); 6729bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 6739bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6749bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonvoid fintek_exit(void) 6759bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson{ 6769bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson pnp_unregister_driver(&fintek_driver); 6779bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson} 6789bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6799bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonmodule_param(debug, int, S_IRUGO | S_IWUSR); 6809bdc79ea07d98386b72e1b6b1613742556fba3afJarod WilsonMODULE_PARM_DESC(debug, "Enable debugging output"); 6819bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6829bdc79ea07d98386b72e1b6b1613742556fba3afJarod WilsonMODULE_DEVICE_TABLE(pnp, fintek_ids); 6839bdc79ea07d98386b72e1b6b1613742556fba3afJarod WilsonMODULE_DESCRIPTION(FINTEK_DESCRIPTION " driver"); 6849bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6859bdc79ea07d98386b72e1b6b1613742556fba3afJarod WilsonMODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); 6869bdc79ea07d98386b72e1b6b1613742556fba3afJarod WilsonMODULE_LICENSE("GPL"); 6879bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilson 6889bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonmodule_init(fintek_init); 6899bdc79ea07d98386b72e1b6b1613742556fba3afJarod Wilsonmodule_exit(fintek_exit); 690