0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/delay.h>
0018 #include <linux/io.h>
0019 #include <linux/kernel.h>
0020 #include <linux/leds.h>
0021 #include <linux/init.h>
0022 #include <linux/platform_data/max197.h>
0023 #include <linux/platform_device.h>
0024 #include <linux/slab.h>
0025
0026
0027 #define TS5500_PRODUCT_CODE_ADDR 0x74
0028 #define TS5500_PRODUCT_CODE 0x60
0029 #define TS5400_PRODUCT_CODE 0x40
0030
0031
0032 #define TS5500_SRAM_RS485_ADC_ADDR 0x75
0033 #define TS5500_SRAM BIT(0)
0034 #define TS5500_RS485 BIT(1)
0035 #define TS5500_ADC BIT(2)
0036 #define TS5500_RS485_RTS BIT(6)
0037 #define TS5500_RS485_AUTO BIT(7)
0038
0039
0040 #define TS5500_ERESET_ITR_ADDR 0x76
0041 #define TS5500_ERESET BIT(0)
0042 #define TS5500_ITR BIT(1)
0043
0044
0045 #define TS5500_LED_JP_ADDR 0x77
0046 #define TS5500_LED BIT(0)
0047 #define TS5500_JP1 BIT(1)
0048 #define TS5500_JP2 BIT(2)
0049 #define TS5500_JP3 BIT(3)
0050 #define TS5500_JP4 BIT(4)
0051 #define TS5500_JP5 BIT(5)
0052 #define TS5500_JP6 BIT(6)
0053 #define TS5500_JP7 BIT(7)
0054
0055
0056 #define TS5500_ADC_CONV_BUSY_ADDR 0x195
0057 #define TS5500_ADC_CONV_BUSY BIT(0)
0058 #define TS5500_ADC_CONV_INIT_LSB_ADDR 0x196
0059 #define TS5500_ADC_CONV_MSB_ADDR 0x197
0060 #define TS5500_ADC_CONV_DELAY 12
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073 struct ts5500_sbc {
0074 const char *name;
0075 int id;
0076 bool sram;
0077 bool rs485;
0078 bool adc;
0079 bool ereset;
0080 bool itr;
0081 u8 jumpers;
0082 };
0083
0084
0085 static const struct {
0086 const char * const string;
0087 const ssize_t offset;
0088 } ts5500_signatures[] __initconst = {
0089 { "TS-5x00 AMD Elan", 0xb14 },
0090 };
0091
0092 static int __init ts5500_check_signature(void)
0093 {
0094 void __iomem *bios;
0095 int i, ret = -ENODEV;
0096
0097 bios = ioremap(0xf0000, 0x10000);
0098 if (!bios)
0099 return -ENOMEM;
0100
0101 for (i = 0; i < ARRAY_SIZE(ts5500_signatures); i++) {
0102 if (check_signature(bios + ts5500_signatures[i].offset,
0103 ts5500_signatures[i].string,
0104 strlen(ts5500_signatures[i].string))) {
0105 ret = 0;
0106 break;
0107 }
0108 }
0109
0110 iounmap(bios);
0111 return ret;
0112 }
0113
0114 static int __init ts5500_detect_config(struct ts5500_sbc *sbc)
0115 {
0116 u8 tmp;
0117 int ret = 0;
0118
0119 if (!request_region(TS5500_PRODUCT_CODE_ADDR, 4, "ts5500"))
0120 return -EBUSY;
0121
0122 sbc->id = inb(TS5500_PRODUCT_CODE_ADDR);
0123 if (sbc->id == TS5500_PRODUCT_CODE) {
0124 sbc->name = "TS-5500";
0125 } else if (sbc->id == TS5400_PRODUCT_CODE) {
0126 sbc->name = "TS-5400";
0127 } else {
0128 pr_err("ts5500: unknown product code 0x%x\n", sbc->id);
0129 ret = -ENODEV;
0130 goto cleanup;
0131 }
0132
0133 tmp = inb(TS5500_SRAM_RS485_ADC_ADDR);
0134 sbc->sram = tmp & TS5500_SRAM;
0135 sbc->rs485 = tmp & TS5500_RS485;
0136 sbc->adc = tmp & TS5500_ADC;
0137
0138 tmp = inb(TS5500_ERESET_ITR_ADDR);
0139 sbc->ereset = tmp & TS5500_ERESET;
0140 sbc->itr = tmp & TS5500_ITR;
0141
0142 tmp = inb(TS5500_LED_JP_ADDR);
0143 sbc->jumpers = tmp & ~TS5500_LED;
0144
0145 cleanup:
0146 release_region(TS5500_PRODUCT_CODE_ADDR, 4);
0147 return ret;
0148 }
0149
0150 static ssize_t name_show(struct device *dev, struct device_attribute *attr,
0151 char *buf)
0152 {
0153 struct ts5500_sbc *sbc = dev_get_drvdata(dev);
0154
0155 return sprintf(buf, "%s\n", sbc->name);
0156 }
0157 static DEVICE_ATTR_RO(name);
0158
0159 static ssize_t id_show(struct device *dev, struct device_attribute *attr,
0160 char *buf)
0161 {
0162 struct ts5500_sbc *sbc = dev_get_drvdata(dev);
0163
0164 return sprintf(buf, "0x%.2x\n", sbc->id);
0165 }
0166 static DEVICE_ATTR_RO(id);
0167
0168 static ssize_t jumpers_show(struct device *dev, struct device_attribute *attr,
0169 char *buf)
0170 {
0171 struct ts5500_sbc *sbc = dev_get_drvdata(dev);
0172
0173 return sprintf(buf, "0x%.2x\n", sbc->jumpers >> 1);
0174 }
0175 static DEVICE_ATTR_RO(jumpers);
0176
0177 #define TS5500_ATTR_BOOL(_field) \
0178 static ssize_t _field##_show(struct device *dev, \
0179 struct device_attribute *attr, char *buf) \
0180 { \
0181 struct ts5500_sbc *sbc = dev_get_drvdata(dev); \
0182 \
0183 return sprintf(buf, "%d\n", sbc->_field); \
0184 } \
0185 static DEVICE_ATTR_RO(_field)
0186
0187 TS5500_ATTR_BOOL(sram);
0188 TS5500_ATTR_BOOL(rs485);
0189 TS5500_ATTR_BOOL(adc);
0190 TS5500_ATTR_BOOL(ereset);
0191 TS5500_ATTR_BOOL(itr);
0192
0193 static struct attribute *ts5500_attributes[] = {
0194 &dev_attr_id.attr,
0195 &dev_attr_name.attr,
0196 &dev_attr_jumpers.attr,
0197 &dev_attr_sram.attr,
0198 &dev_attr_rs485.attr,
0199 &dev_attr_adc.attr,
0200 &dev_attr_ereset.attr,
0201 &dev_attr_itr.attr,
0202 NULL
0203 };
0204
0205 static const struct attribute_group ts5500_attr_group = {
0206 .attrs = ts5500_attributes,
0207 };
0208
0209 static struct resource ts5500_dio1_resource[] = {
0210 DEFINE_RES_IRQ_NAMED(7, "DIO1 interrupt"),
0211 };
0212
0213 static struct platform_device ts5500_dio1_pdev = {
0214 .name = "ts5500-dio1",
0215 .id = -1,
0216 .resource = ts5500_dio1_resource,
0217 .num_resources = 1,
0218 };
0219
0220 static struct resource ts5500_dio2_resource[] = {
0221 DEFINE_RES_IRQ_NAMED(6, "DIO2 interrupt"),
0222 };
0223
0224 static struct platform_device ts5500_dio2_pdev = {
0225 .name = "ts5500-dio2",
0226 .id = -1,
0227 .resource = ts5500_dio2_resource,
0228 .num_resources = 1,
0229 };
0230
0231 static void ts5500_led_set(struct led_classdev *led_cdev,
0232 enum led_brightness brightness)
0233 {
0234 outb(!!brightness, TS5500_LED_JP_ADDR);
0235 }
0236
0237 static enum led_brightness ts5500_led_get(struct led_classdev *led_cdev)
0238 {
0239 return (inb(TS5500_LED_JP_ADDR) & TS5500_LED) ? LED_FULL : LED_OFF;
0240 }
0241
0242 static struct led_classdev ts5500_led_cdev = {
0243 .name = "ts5500:green:",
0244 .brightness_set = ts5500_led_set,
0245 .brightness_get = ts5500_led_get,
0246 };
0247
0248 static int ts5500_adc_convert(u8 ctrl)
0249 {
0250 u8 lsb, msb;
0251
0252
0253 outb(ctrl & 0x1f, TS5500_ADC_CONV_INIT_LSB_ADDR);
0254
0255
0256
0257
0258
0259
0260 udelay(TS5500_ADC_CONV_DELAY);
0261 if (inb(TS5500_ADC_CONV_BUSY_ADDR) & TS5500_ADC_CONV_BUSY)
0262 return -EBUSY;
0263
0264
0265 lsb = inb(TS5500_ADC_CONV_INIT_LSB_ADDR);
0266 msb = inb(TS5500_ADC_CONV_MSB_ADDR);
0267
0268 return (msb << 8) | lsb;
0269 }
0270
0271 static struct max197_platform_data ts5500_adc_pdata = {
0272 .convert = ts5500_adc_convert,
0273 };
0274
0275 static struct platform_device ts5500_adc_pdev = {
0276 .name = "max197",
0277 .id = -1,
0278 .dev = {
0279 .platform_data = &ts5500_adc_pdata,
0280 },
0281 };
0282
0283 static int __init ts5500_init(void)
0284 {
0285 struct platform_device *pdev;
0286 struct ts5500_sbc *sbc;
0287 int err;
0288
0289
0290
0291
0292
0293
0294 err = ts5500_check_signature();
0295 if (err)
0296 return err;
0297
0298 pdev = platform_device_register_simple("ts5500", -1, NULL, 0);
0299 if (IS_ERR(pdev))
0300 return PTR_ERR(pdev);
0301
0302 sbc = devm_kzalloc(&pdev->dev, sizeof(struct ts5500_sbc), GFP_KERNEL);
0303 if (!sbc) {
0304 err = -ENOMEM;
0305 goto error;
0306 }
0307
0308 err = ts5500_detect_config(sbc);
0309 if (err)
0310 goto error;
0311
0312 platform_set_drvdata(pdev, sbc);
0313
0314 err = sysfs_create_group(&pdev->dev.kobj, &ts5500_attr_group);
0315 if (err)
0316 goto error;
0317
0318 if (sbc->id == TS5500_PRODUCT_CODE) {
0319 ts5500_dio1_pdev.dev.parent = &pdev->dev;
0320 if (platform_device_register(&ts5500_dio1_pdev))
0321 dev_warn(&pdev->dev, "DIO1 block registration failed\n");
0322 ts5500_dio2_pdev.dev.parent = &pdev->dev;
0323 if (platform_device_register(&ts5500_dio2_pdev))
0324 dev_warn(&pdev->dev, "DIO2 block registration failed\n");
0325 }
0326
0327 if (led_classdev_register(&pdev->dev, &ts5500_led_cdev))
0328 dev_warn(&pdev->dev, "LED registration failed\n");
0329
0330 if (sbc->adc) {
0331 ts5500_adc_pdev.dev.parent = &pdev->dev;
0332 if (platform_device_register(&ts5500_adc_pdev))
0333 dev_warn(&pdev->dev, "ADC registration failed\n");
0334 }
0335
0336 return 0;
0337 error:
0338 platform_device_unregister(pdev);
0339 return err;
0340 }
0341 device_initcall(ts5500_init);