Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR
0004  *
0005  * Copyright (C) 2010 Jarod Wilson <jarod@redhat.com>
0006  * Copyright (C) 2009 Nuvoton PS Team
0007  *
0008  * Special thanks to Nuvoton for providing hardware, spec sheets and
0009  * sample code upon which portions of this driver are based. Indirect
0010  * thanks also to Maxim Levitsky, whose ene_ir driver this driver is
0011  * modeled after.
0012  */
0013 
0014 #include <linux/spinlock.h>
0015 #include <linux/ioctl.h>
0016 
0017 /* platform driver name to register */
0018 #define NVT_DRIVER_NAME "nuvoton-cir"
0019 
0020 /* debugging module parameter */
0021 static int debug;
0022 
0023 
0024 #define nvt_dbg(text, ...) \
0025     if (debug) \
0026         printk(KERN_DEBUG \
0027             KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
0028 
0029 #define nvt_dbg_verbose(text, ...) \
0030     if (debug > 1) \
0031         printk(KERN_DEBUG \
0032             KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
0033 
0034 #define nvt_dbg_wake(text, ...) \
0035     if (debug > 2) \
0036         printk(KERN_DEBUG \
0037             KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
0038 
0039 
0040 #define RX_BUF_LEN 32
0041 
0042 #define SIO_ID_MASK 0xfff0
0043 
0044 enum nvt_chip_ver {
0045     NVT_UNKNOWN = 0,
0046     NVT_W83667HG    = 0xa510,
0047     NVT_6775F   = 0xb470,
0048     NVT_6776F   = 0xc330,
0049     NVT_6779D   = 0xc560,
0050     NVT_INVALID = 0xffff,
0051 };
0052 
0053 struct nvt_chip {
0054     const char *name;
0055     enum nvt_chip_ver chip_ver;
0056 };
0057 
0058 struct nvt_dev {
0059     struct rc_dev *rdev;
0060 
0061     spinlock_t lock;
0062 
0063     /* for rx */
0064     u8 buf[RX_BUF_LEN];
0065     unsigned int pkts;
0066 
0067     /* EFER Config register index/data pair */
0068     u32 cr_efir;
0069     u32 cr_efdr;
0070 
0071     /* hardware I/O settings */
0072     unsigned long cir_addr;
0073     unsigned long cir_wake_addr;
0074     int cir_irq;
0075 
0076     enum nvt_chip_ver chip_ver;
0077     /* hardware id */
0078     u8 chip_major;
0079     u8 chip_minor;
0080 
0081     /* carrier period = 1 / frequency */
0082     u32 carrier;
0083 };
0084 
0085 /* buffer packet constants */
0086 #define BUF_PULSE_BIT   0x80
0087 #define BUF_LEN_MASK    0x7f
0088 #define BUF_REPEAT_BYTE 0x70
0089 #define BUF_REPEAT_MASK 0xf0
0090 
0091 /* CIR settings */
0092 
0093 /* total length of CIR and CIR WAKE */
0094 #define CIR_IOREG_LENGTH    0x0f
0095 
0096 /* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL */
0097 #define CIR_RX_LIMIT_COUNT  (IR_DEFAULT_TIMEOUT / SAMPLE_PERIOD)
0098 
0099 /* CIR Regs */
0100 #define CIR_IRCON   0x00
0101 #define CIR_IRSTS   0x01
0102 #define CIR_IREN    0x02
0103 #define CIR_RXFCONT 0x03
0104 #define CIR_CP      0x04
0105 #define CIR_CC      0x05
0106 #define CIR_SLCH    0x06
0107 #define CIR_SLCL    0x07
0108 #define CIR_FIFOCON 0x08
0109 #define CIR_IRFIFOSTS   0x09
0110 #define CIR_SRXFIFO 0x0a
0111 #define CIR_TXFCONT 0x0b
0112 #define CIR_STXFIFO 0x0c
0113 #define CIR_FCCH    0x0d
0114 #define CIR_FCCL    0x0e
0115 #define CIR_IRFSM   0x0f
0116 
0117 /* CIR IRCON settings */
0118 #define CIR_IRCON_RECV   0x80
0119 #define CIR_IRCON_WIREN  0x40
0120 #define CIR_IRCON_TXEN   0x20
0121 #define CIR_IRCON_RXEN   0x10
0122 #define CIR_IRCON_WRXINV 0x08
0123 #define CIR_IRCON_RXINV  0x04
0124 
0125 #define CIR_IRCON_SAMPLE_PERIOD_SEL_1   0x00
0126 #define CIR_IRCON_SAMPLE_PERIOD_SEL_25  0x01
0127 #define CIR_IRCON_SAMPLE_PERIOD_SEL_50  0x02
0128 #define CIR_IRCON_SAMPLE_PERIOD_SEL_100 0x03
0129 
0130 /* FIXME: make this a runtime option */
0131 /* select sample period as 50us */
0132 #define CIR_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50
0133 
0134 /* CIR IRSTS settings */
0135 #define CIR_IRSTS_RDR   0x80
0136 #define CIR_IRSTS_RTR   0x40
0137 #define CIR_IRSTS_PE    0x20
0138 #define CIR_IRSTS_RFO   0x10
0139 #define CIR_IRSTS_TE    0x08
0140 #define CIR_IRSTS_TTR   0x04
0141 #define CIR_IRSTS_TFU   0x02
0142 #define CIR_IRSTS_GH    0x01
0143 
0144 /* CIR IREN settings */
0145 #define CIR_IREN_RDR    0x80
0146 #define CIR_IREN_RTR    0x40
0147 #define CIR_IREN_PE 0x20
0148 #define CIR_IREN_RFO    0x10
0149 #define CIR_IREN_TE 0x08
0150 #define CIR_IREN_TTR    0x04
0151 #define CIR_IREN_TFU    0x02
0152 #define CIR_IREN_GH 0x01
0153 
0154 /* CIR FIFOCON settings */
0155 #define CIR_FIFOCON_TXFIFOCLR       0x80
0156 
0157 #define CIR_FIFOCON_TX_TRIGGER_LEV_31   0x00
0158 #define CIR_FIFOCON_TX_TRIGGER_LEV_24   0x10
0159 #define CIR_FIFOCON_TX_TRIGGER_LEV_16   0x20
0160 #define CIR_FIFOCON_TX_TRIGGER_LEV_8    0x30
0161 
0162 /* FIXME: make this a runtime option */
0163 /* select TX trigger level as 16 */
0164 #define CIR_FIFOCON_TX_TRIGGER_LEV  CIR_FIFOCON_TX_TRIGGER_LEV_16
0165 
0166 #define CIR_FIFOCON_RXFIFOCLR       0x08
0167 
0168 #define CIR_FIFOCON_RX_TRIGGER_LEV_1    0x00
0169 #define CIR_FIFOCON_RX_TRIGGER_LEV_8    0x01
0170 #define CIR_FIFOCON_RX_TRIGGER_LEV_16   0x02
0171 #define CIR_FIFOCON_RX_TRIGGER_LEV_24   0x03
0172 
0173 /* FIXME: make this a runtime option */
0174 /* select RX trigger level as 24 */
0175 #define CIR_FIFOCON_RX_TRIGGER_LEV  CIR_FIFOCON_RX_TRIGGER_LEV_24
0176 
0177 /* CIR IRFIFOSTS settings */
0178 #define CIR_IRFIFOSTS_IR_PENDING    0x80
0179 #define CIR_IRFIFOSTS_RX_GS     0x40
0180 #define CIR_IRFIFOSTS_RX_FTA        0x20
0181 #define CIR_IRFIFOSTS_RX_EMPTY      0x10
0182 #define CIR_IRFIFOSTS_RX_FULL       0x08
0183 #define CIR_IRFIFOSTS_TX_FTA        0x04
0184 #define CIR_IRFIFOSTS_TX_EMPTY      0x02
0185 #define CIR_IRFIFOSTS_TX_FULL       0x01
0186 
0187 
0188 /* CIR WAKE UP Regs */
0189 #define CIR_WAKE_IRCON          0x00
0190 #define CIR_WAKE_IRSTS          0x01
0191 #define CIR_WAKE_IREN           0x02
0192 #define CIR_WAKE_FIFO_CMP_DEEP      0x03
0193 #define CIR_WAKE_FIFO_CMP_TOL       0x04
0194 #define CIR_WAKE_FIFO_COUNT     0x05
0195 #define CIR_WAKE_SLCH           0x06
0196 #define CIR_WAKE_SLCL           0x07
0197 #define CIR_WAKE_FIFOCON        0x08
0198 #define CIR_WAKE_SRXFSTS        0x09
0199 #define CIR_WAKE_SAMPLE_RX_FIFO     0x0a
0200 #define CIR_WAKE_WR_FIFO_DATA       0x0b
0201 #define CIR_WAKE_RD_FIFO_ONLY       0x0c
0202 #define CIR_WAKE_RD_FIFO_ONLY_IDX   0x0d
0203 #define CIR_WAKE_FIFO_IGNORE        0x0e
0204 #define CIR_WAKE_IRFSM          0x0f
0205 
0206 /* CIR WAKE UP IRCON settings */
0207 #define CIR_WAKE_IRCON_DEC_RST      0x80
0208 #define CIR_WAKE_IRCON_MODE1        0x40
0209 #define CIR_WAKE_IRCON_MODE0        0x20
0210 #define CIR_WAKE_IRCON_RXEN     0x10
0211 #define CIR_WAKE_IRCON_R        0x08
0212 #define CIR_WAKE_IRCON_RXINV        0x04
0213 
0214 /* FIXME/jarod: make this a runtime option */
0215 /* select a same sample period like cir register */
0216 #define CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL    CIR_IRCON_SAMPLE_PERIOD_SEL_50
0217 
0218 /* CIR WAKE IRSTS Bits */
0219 #define CIR_WAKE_IRSTS_RDR      0x80
0220 #define CIR_WAKE_IRSTS_RTR      0x40
0221 #define CIR_WAKE_IRSTS_PE       0x20
0222 #define CIR_WAKE_IRSTS_RFO      0x10
0223 #define CIR_WAKE_IRSTS_GH       0x08
0224 #define CIR_WAKE_IRSTS_IR_PENDING   0x01
0225 
0226 /* CIR WAKE UP IREN Bits */
0227 #define CIR_WAKE_IREN_RDR       0x80
0228 #define CIR_WAKE_IREN_RTR       0x40
0229 #define CIR_WAKE_IREN_PE        0x20
0230 #define CIR_WAKE_IREN_RFO       0x10
0231 #define CIR_WAKE_IREN_GH        0x08
0232 
0233 /* CIR WAKE FIFOCON settings */
0234 #define CIR_WAKE_FIFOCON_RXFIFOCLR  0x08
0235 
0236 #define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67  0x00
0237 #define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_66  0x01
0238 #define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_65  0x02
0239 #define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_64  0x03
0240 
0241 /* FIXME: make this a runtime option */
0242 /* select WAKE UP RX trigger level as 67 */
0243 #define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67
0244 
0245 /* CIR WAKE SRXFSTS settings */
0246 #define CIR_WAKE_IRFIFOSTS_RX_GS    0x80
0247 #define CIR_WAKE_IRFIFOSTS_RX_FTA   0x40
0248 #define CIR_WAKE_IRFIFOSTS_RX_EMPTY 0x20
0249 #define CIR_WAKE_IRFIFOSTS_RX_FULL  0x10
0250 
0251 /*
0252  * The CIR Wake FIFO buffer is 67 bytes long, but the stock remote wakes
0253  * the system comparing only 65 bytes (fails with this set to 67)
0254  */
0255 #define CIR_WAKE_FIFO_CMP_BYTES     65
0256 /* CIR Wake byte comparison tolerance */
0257 #define CIR_WAKE_CMP_TOLERANCE      5
0258 
0259 /*
0260  * Extended Function Enable Registers:
0261  *  Extended Function Index Register
0262  *  Extended Function Data Register
0263  */
0264 #define CR_EFIR         0x2e
0265 #define CR_EFDR         0x2f
0266 
0267 /* Possible alternate EFER values, depends on how the chip is wired */
0268 #define CR_EFIR2        0x4e
0269 #define CR_EFDR2        0x4f
0270 
0271 /* Extended Function Mode enable/disable magic values */
0272 #define EFER_EFM_ENABLE     0x87
0273 #define EFER_EFM_DISABLE    0xaa
0274 
0275 /* Config regs we need to care about */
0276 #define CR_SOFTWARE_RESET   0x02
0277 #define CR_LOGICAL_DEV_SEL  0x07
0278 #define CR_CHIP_ID_HI       0x20
0279 #define CR_CHIP_ID_LO       0x21
0280 #define CR_DEV_POWER_DOWN   0x22 /* bit 2 is CIR power, default power on */
0281 #define CR_OUTPUT_PIN_SEL   0x27
0282 #define CR_MULTIFUNC_PIN_SEL    0x2c
0283 #define CR_LOGICAL_DEV_EN   0x30 /* valid for all logical devices */
0284 /* next three regs valid for both the CIR and CIR_WAKE logical devices */
0285 #define CR_CIR_BASE_ADDR_HI 0x60
0286 #define CR_CIR_BASE_ADDR_LO 0x61
0287 #define CR_CIR_IRQ_RSRC     0x70
0288 /* next three regs valid only for ACPI logical dev */
0289 #define CR_ACPI_CIR_WAKE    0xe0
0290 #define CR_ACPI_IRQ_EVENTS  0xf6
0291 #define CR_ACPI_IRQ_EVENTS2 0xf7
0292 
0293 /* Logical devices that we need to care about */
0294 #define LOGICAL_DEV_LPT     0x01
0295 #define LOGICAL_DEV_CIR     0x06
0296 #define LOGICAL_DEV_ACPI    0x0a
0297 #define LOGICAL_DEV_CIR_WAKE    0x0e
0298 
0299 #define LOGICAL_DEV_DISABLE 0x00
0300 #define LOGICAL_DEV_ENABLE  0x01
0301 
0302 #define CIR_WAKE_ENABLE_BIT 0x08
0303 #define PME_INTR_CIR_PASS_BIT   0x08
0304 
0305 /* w83677hg CIR pin config */
0306 #define OUTPUT_PIN_SEL_MASK 0xbc
0307 #define OUTPUT_ENABLE_CIR   0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */
0308 #define OUTPUT_ENABLE_CIRWB 0x40 /* enable wide-band sensor */
0309 
0310 /* w83667hg CIR pin config */
0311 #define MULTIFUNC_PIN_SEL_MASK  0x1f
0312 #define MULTIFUNC_ENABLE_CIR    0x80 /* Pin75=CIRRX, Pin76=CIRTX1 */
0313 #define MULTIFUNC_ENABLE_CIRWB  0x20 /* enable wide-band sensor */
0314 
0315 /* MCE CIR signal length, related on sample period */
0316 
0317 /* MCE CIR controller signal length: about 43ms
0318  * 43ms / 50us (sample period) * 0.85 (inaccuracy)
0319  */
0320 #define CONTROLLER_BUF_LEN_MIN 830
0321 
0322 /* MCE CIR keyboard signal length: about 26ms
0323  * 26ms / 50us (sample period) * 0.85 (inaccuracy)
0324  */
0325 #define KEYBOARD_BUF_LEN_MAX 650
0326 #define KEYBOARD_BUF_LEN_MIN 610
0327 
0328 /* MCE CIR mouse signal length: about 24ms
0329  * 24ms / 50us (sample period) * 0.85 (inaccuracy)
0330  */
0331 #define MOUSE_BUF_LEN_MIN 565
0332 
0333 #define CIR_SAMPLE_PERIOD 50
0334 #define CIR_SAMPLE_LOW_INACCURACY 0.85
0335 
0336 /* MAX silence time that driver will sent to lirc */
0337 #define MAX_SILENCE_TIME 60000
0338 
0339 #if CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_100
0340 #define SAMPLE_PERIOD 100
0341 
0342 #elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_50
0343 #define SAMPLE_PERIOD 50
0344 
0345 #elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_25
0346 #define SAMPLE_PERIOD 25
0347 
0348 #else
0349 #define SAMPLE_PERIOD 1
0350 #endif
0351 
0352 /* as VISTA MCE definition, valid carrier value */
0353 #define MAX_CARRIER 60000
0354 #define MIN_CARRIER 30000
0355 
0356 /* max wakeup sequence length */
0357 #define WAKEUP_MAX_SIZE 65