aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/sony-laptop.c204
1 files changed, 148 insertions, 56 deletions
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index d38ddce592c0..f248080828f2 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -1173,7 +1173,8 @@ static struct acpi_driver sony_nc_driver = {
1173#define SONYPI_TYPE3_OFFSET 0x12 1173#define SONYPI_TYPE3_OFFSET 0x12
1174 1174
1175struct sony_pic_ioport { 1175struct sony_pic_ioport {
1176 struct acpi_resource_io io; 1176 struct acpi_resource_io io1;
1177 struct acpi_resource_io io2;
1177 struct list_head list; 1178 struct list_head list;
1178}; 1179};
1179 1180
@@ -1443,11 +1444,11 @@ static u8 sony_pic_call1(u8 dev)
1443{ 1444{
1444 u8 v1, v2; 1445 u8 v1, v2;
1445 1446
1446 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, 1447 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
1447 ITERATIONS_LONG); 1448 ITERATIONS_LONG);
1448 outb(dev, spic_dev.cur_ioport->io.minimum + 4); 1449 outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
1449 v1 = inb_p(spic_dev.cur_ioport->io.minimum + 4); 1450 v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4);
1450 v2 = inb_p(spic_dev.cur_ioport->io.minimum); 1451 v2 = inb_p(spic_dev.cur_ioport->io1.minimum);
1451 dprintk("sony_pic_call1: 0x%.4x\n", (v2 << 8) | v1); 1452 dprintk("sony_pic_call1: 0x%.4x\n", (v2 << 8) | v1);
1452 return v2; 1453 return v2;
1453} 1454}
@@ -1456,13 +1457,13 @@ static u8 sony_pic_call2(u8 dev, u8 fn)
1456{ 1457{
1457 u8 v1; 1458 u8 v1;
1458 1459
1459 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, 1460 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
1460 ITERATIONS_LONG); 1461 ITERATIONS_LONG);
1461 outb(dev, spic_dev.cur_ioport->io.minimum + 4); 1462 outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
1462 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, 1463 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
1463 ITERATIONS_LONG); 1464 ITERATIONS_LONG);
1464 outb(fn, spic_dev.cur_ioport->io.minimum); 1465 outb(fn, spic_dev.cur_ioport->io1.minimum);
1465 v1 = inb_p(spic_dev.cur_ioport->io.minimum); 1466 v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
1466 dprintk("sony_pic_call2: 0x%.4x\n", v1); 1467 dprintk("sony_pic_call2: 0x%.4x\n", v1);
1467 return v1; 1468 return v1;
1468} 1469}
@@ -1471,13 +1472,13 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
1471{ 1472{
1472 u8 v1; 1473 u8 v1;
1473 1474
1474 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG); 1475 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
1475 outb(dev, spic_dev.cur_ioport->io.minimum + 4); 1476 outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
1476 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG); 1477 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
1477 outb(fn, spic_dev.cur_ioport->io.minimum); 1478 outb(fn, spic_dev.cur_ioport->io1.minimum);
1478 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG); 1479 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
1479 outb(v, spic_dev.cur_ioport->io.minimum); 1480 outb(v, spic_dev.cur_ioport->io1.minimum);
1480 v1 = inb_p(spic_dev.cur_ioport->io.minimum); 1481 v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
1481 dprintk("sony_pic_call3: 0x%.4x\n", v1); 1482 dprintk("sony_pic_call3: 0x%.4x\n", v1);
1482 return v1; 1483 return v1;
1483} 1484}
@@ -2074,7 +2075,18 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
2074 2075
2075 switch (resource->type) { 2076 switch (resource->type) {
2076 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 2077 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
2078 {
2079 /* start IO enumeration */
2080 struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
2081 if (!ioport)
2082 return AE_ERROR;
2083
2084 list_add(&ioport->list, &dev->ioports);
2085 return AE_OK;
2086 }
2087
2077 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 2088 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
2089 /* end IO enumeration */
2078 return AE_OK; 2090 return AE_OK;
2079 2091
2080 case ACPI_RESOURCE_TYPE_IRQ: 2092 case ACPI_RESOURCE_TYPE_IRQ:
@@ -2101,7 +2113,7 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
2101 if (!interrupt) 2113 if (!interrupt)
2102 return AE_ERROR; 2114 return AE_ERROR;
2103 2115
2104 list_add_tail(&interrupt->list, &dev->interrupts); 2116 list_add(&interrupt->list, &dev->interrupts);
2105 interrupt->irq.triggering = p->triggering; 2117 interrupt->irq.triggering = p->triggering;
2106 interrupt->irq.polarity = p->polarity; 2118 interrupt->irq.polarity = p->polarity;
2107 interrupt->irq.sharable = p->sharable; 2119 interrupt->irq.sharable = p->sharable;
@@ -2113,18 +2125,27 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
2113 case ACPI_RESOURCE_TYPE_IO: 2125 case ACPI_RESOURCE_TYPE_IO:
2114 { 2126 {
2115 struct acpi_resource_io *io = &resource->data.io; 2127 struct acpi_resource_io *io = &resource->data.io;
2116 struct sony_pic_ioport *ioport = NULL; 2128 struct sony_pic_ioport *ioport =
2129 list_first_entry(&dev->ioports, struct sony_pic_ioport, list);
2117 if (!io) { 2130 if (!io) {
2118 dprintk("Blank IO resource\n"); 2131 dprintk("Blank IO resource\n");
2119 return AE_OK; 2132 return AE_OK;
2120 } 2133 }
2121 2134
2122 ioport = kzalloc(sizeof(*ioport), GFP_KERNEL); 2135 if (!ioport->io1.minimum) {
2123 if (!ioport) 2136 memcpy(&ioport->io1, io, sizeof(*io));
2137 dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum,
2138 ioport->io1.address_length);
2139 }
2140 else if (!ioport->io2.minimum) {
2141 memcpy(&ioport->io2, io, sizeof(*io));
2142 dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum,
2143 ioport->io2.address_length);
2144 }
2145 else {
2146 printk(KERN_ERR DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n");
2124 return AE_ERROR; 2147 return AE_ERROR;
2125 2148 }
2126 list_add_tail(&ioport->list, &dev->ioports);
2127 memcpy(&ioport->io, io, sizeof(*io));
2128 return AE_OK; 2149 return AE_OK;
2129 } 2150 }
2130 default: 2151 default:
@@ -2199,10 +2220,22 @@ static int sony_pic_enable(struct acpi_device *device,
2199{ 2220{
2200 acpi_status status; 2221 acpi_status status;
2201 int result = 0; 2222 int result = 0;
2223 /* Type 1 resource layout is:
2224 * IO
2225 * IO
2226 * IRQNoFlags
2227 * End
2228 *
2229 * Type 2 and 3 resource layout is:
2230 * IO
2231 * IRQNoFlags
2232 * End
2233 */
2202 struct { 2234 struct {
2203 struct acpi_resource io_res; 2235 struct acpi_resource res1;
2204 struct acpi_resource irq_res; 2236 struct acpi_resource res2;
2205 struct acpi_resource end; 2237 struct acpi_resource res3;
2238 struct acpi_resource res4;
2206 } *resource; 2239 } *resource;
2207 struct acpi_buffer buffer = { 0, NULL }; 2240 struct acpi_buffer buffer = { 0, NULL };
2208 2241
@@ -2217,21 +2250,49 @@ static int sony_pic_enable(struct acpi_device *device,
2217 buffer.length = sizeof(*resource) + 1; 2250 buffer.length = sizeof(*resource) + 1;
2218 buffer.pointer = resource; 2251 buffer.pointer = resource;
2219 2252
2220 /* setup io resource */ 2253 /* setup Type 1 resources */
2221 resource->io_res.type = ACPI_RESOURCE_TYPE_IO; 2254 if (spic_dev.model == SONYPI_DEVICE_TYPE1) {
2222 resource->io_res.length = sizeof(struct acpi_resource);
2223 memcpy(&resource->io_res.data.io, &ioport->io,
2224 sizeof(struct acpi_resource_io));
2225 2255
2226 /* setup irq resource */ 2256 /* setup io resources */
2227 resource->irq_res.type = ACPI_RESOURCE_TYPE_IRQ; 2257 resource->res1.type = ACPI_RESOURCE_TYPE_IO;
2228 resource->irq_res.length = sizeof(struct acpi_resource); 2258 resource->res1.length = sizeof(struct acpi_resource);
2229 memcpy(&resource->irq_res.data.irq, &irq->irq, 2259 memcpy(&resource->res1.data.io, &ioport->io1,
2230 sizeof(struct acpi_resource_irq)); 2260 sizeof(struct acpi_resource_io));
2231 /* we requested a shared irq */
2232 resource->irq_res.data.irq.sharable = ACPI_SHARED;
2233 2261
2234 resource->end.type = ACPI_RESOURCE_TYPE_END_TAG; 2262 resource->res2.type = ACPI_RESOURCE_TYPE_IO;
2263 resource->res2.length = sizeof(struct acpi_resource);
2264 memcpy(&resource->res2.data.io, &ioport->io2,
2265 sizeof(struct acpi_resource_io));
2266
2267 /* setup irq resource */
2268 resource->res3.type = ACPI_RESOURCE_TYPE_IRQ;
2269 resource->res3.length = sizeof(struct acpi_resource);
2270 memcpy(&resource->res3.data.irq, &irq->irq,
2271 sizeof(struct acpi_resource_irq));
2272 /* we requested a shared irq */
2273 resource->res3.data.irq.sharable = ACPI_SHARED;
2274
2275 resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG;
2276
2277 }
2278 /* setup Type 2/3 resources */
2279 else {
2280 /* setup io resource */
2281 resource->res1.type = ACPI_RESOURCE_TYPE_IO;
2282 resource->res1.length = sizeof(struct acpi_resource);
2283 memcpy(&resource->res1.data.io, &ioport->io1,
2284 sizeof(struct acpi_resource_io));
2285
2286 /* setup irq resource */
2287 resource->res2.type = ACPI_RESOURCE_TYPE_IRQ;
2288 resource->res2.length = sizeof(struct acpi_resource);
2289 memcpy(&resource->res2.data.irq, &irq->irq,
2290 sizeof(struct acpi_resource_irq));
2291 /* we requested a shared irq */
2292 resource->res2.data.irq.sharable = ACPI_SHARED;
2293
2294 resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG;
2295 }
2235 2296
2236 /* Attempt to set the resource */ 2297 /* Attempt to set the resource */
2237 dprintk("Evaluating _SRS\n"); 2298 dprintk("Evaluating _SRS\n");
@@ -2239,7 +2300,7 @@ static int sony_pic_enable(struct acpi_device *device,
2239 2300
2240 /* check for total failure */ 2301 /* check for total failure */
2241 if (ACPI_FAILURE(status)) { 2302 if (ACPI_FAILURE(status)) {
2242 printk(KERN_ERR DRV_PFX "Error evaluating _SRS"); 2303 printk(KERN_ERR DRV_PFX "Error evaluating _SRS\n");
2243 result = -ENODEV; 2304 result = -ENODEV;
2244 goto end; 2305 goto end;
2245 } 2306 }
@@ -2268,11 +2329,14 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)
2268 2329
2269 struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id; 2330 struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id;
2270 2331
2271 ev = inb_p(dev->cur_ioport->io.minimum); 2332 ev = inb_p(dev->cur_ioport->io1.minimum);
2272 data_mask = inb_p(dev->cur_ioport->io.minimum + dev->evport_offset); 2333 if (dev->cur_ioport->io2.minimum)
2334 data_mask = inb_p(dev->cur_ioport->io2.minimum);
2335 else
2336 data_mask = inb_p(dev->cur_ioport->io1.minimum + dev->evport_offset);
2273 2337
2274 dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", 2338 dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
2275 ev, data_mask, dev->cur_ioport->io.minimum, dev->evport_offset); 2339 ev, data_mask, dev->cur_ioport->io1.minimum, dev->evport_offset);
2276 2340
2277 if (ev == 0x00 || ev == 0xff) 2341 if (ev == 0x00 || ev == 0xff)
2278 return IRQ_HANDLED; 2342 return IRQ_HANDLED;
@@ -2323,8 +2387,11 @@ static int sony_pic_remove(struct acpi_device *device, int type)
2323 } 2387 }
2324 2388
2325 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev); 2389 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
2326 release_region(spic_dev.cur_ioport->io.minimum, 2390 release_region(spic_dev.cur_ioport->io1.minimum,
2327 spic_dev.cur_ioport->io.address_length); 2391 spic_dev.cur_ioport->io1.address_length);
2392 if (spic_dev.cur_ioport->io2.minimum)
2393 release_region(spic_dev.cur_ioport->io2.minimum,
2394 spic_dev.cur_ioport->io2.address_length);
2328 2395
2329 sonypi_compat_exit(); 2396 sonypi_compat_exit();
2330 2397
@@ -2397,14 +2464,36 @@ static int sony_pic_add(struct acpi_device *device)
2397 goto err_remove_input; 2464 goto err_remove_input;
2398 2465
2399 /* request io port */ 2466 /* request io port */
2400 list_for_each_entry(io, &spic_dev.ioports, list) { 2467 list_for_each_entry_reverse(io, &spic_dev.ioports, list) {
2401 if (request_region(io->io.minimum, io->io.address_length, 2468 if (request_region(io->io1.minimum, io->io1.address_length,
2402 "Sony Programable I/O Device")) { 2469 "Sony Programable I/O Device")) {
2403 dprintk("I/O port: 0x%.4x (0x%.4x) + 0x%.2x\n", 2470 dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
2404 io->io.minimum, io->io.maximum, 2471 io->io1.minimum, io->io1.maximum,
2405 io->io.address_length); 2472 io->io1.address_length);
2406 spic_dev.cur_ioport = io; 2473 /* Type 1 have 2 ioports */
2407 break; 2474 if (io->io2.minimum) {
2475 if (request_region(io->io2.minimum,
2476 io->io2.address_length,
2477 "Sony Programable I/O Device")) {
2478 dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
2479 io->io2.minimum, io->io2.maximum,
2480 io->io2.address_length);
2481 spic_dev.cur_ioport = io;
2482 break;
2483 }
2484 else {
2485 dprintk("Unable to get I/O port2: "
2486 "0x%.4x (0x%.4x) + 0x%.2x\n",
2487 io->io2.minimum, io->io2.maximum,
2488 io->io2.address_length);
2489 release_region(io->io1.minimum,
2490 io->io1.address_length);
2491 }
2492 }
2493 else {
2494 spic_dev.cur_ioport = io;
2495 break;
2496 }
2408 } 2497 }
2409 } 2498 }
2410 if (!spic_dev.cur_ioport) { 2499 if (!spic_dev.cur_ioport) {
@@ -2414,7 +2503,7 @@ static int sony_pic_add(struct acpi_device *device)
2414 } 2503 }
2415 2504
2416 /* request IRQ */ 2505 /* request IRQ */
2417 list_for_each_entry(irq, &spic_dev.interrupts, list) { 2506 list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
2418 if (!request_irq(irq->irq.interrupts[0], sony_pic_irq, 2507 if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
2419 IRQF_SHARED, "sony-laptop", &spic_dev)) { 2508 IRQF_SHARED, "sony-laptop", &spic_dev)) {
2420 dprintk("IRQ: %d - triggering: %d - " 2509 dprintk("IRQ: %d - triggering: %d - "
@@ -2462,8 +2551,11 @@ err_free_irq:
2462 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev); 2551 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
2463 2552
2464err_release_region: 2553err_release_region:
2465 release_region(spic_dev.cur_ioport->io.minimum, 2554 release_region(spic_dev.cur_ioport->io1.minimum,
2466 spic_dev.cur_ioport->io.address_length); 2555 spic_dev.cur_ioport->io1.address_length);
2556 if (spic_dev.cur_ioport->io2.minimum)
2557 release_region(spic_dev.cur_ioport->io2.minimum,
2558 spic_dev.cur_ioport->io2.address_length);
2467 2559
2468err_remove_compat: 2560err_remove_compat:
2469 sonypi_compat_exit(); 2561 sonypi_compat_exit();