// SPDX-License-Identifier: GPL-2.0-only /* * Compaq iPAQ h3xxx Atmel microcontroller companion support * * This is an Atmel AT90LS8535 with a special flashed-in firmware that * implements the special protocol used by this driver. * * based on previous kernel 2.4 version by Andrew Christian * Author : Alessandro Gardich <gremlin@gremlin.it> * Author : Dmitry Artamonow <mad_soft@inbox.ru> * Author : Linus Walleij <linus.walleij@linaro.org>
*/
spin_lock(µ->lock); switch (id) { case MSG_VERSION: case MSG_EEPROM_READ: case MSG_EEPROM_WRITE: case MSG_BACKLIGHT: case MSG_NOTIFY_LED: case MSG_THERMAL_SENSOR: case MSG_BATTERY: /* Handle synchronous messages */ if (micro->msg && micro->msg->id == id) { struct ipaq_micro_msg *msg = micro->msg;
memcpy(msg->rx_data, data, len);
msg->rx_len = len;
complete(µ->msg->ack); if (!list_empty(µ->queue)) {
micro->msg = list_entry(micro->queue.next, struct ipaq_micro_msg,
node);
list_del_init(µ->msg->node);
ipaq_micro_trigger_tx(micro);
} else
micro->msg = NULL;
dev_dbg(micro->dev, "OK RX message 0x%02x\n", id);
} else {
dev_err(micro->dev, "out of band RX message 0x%02x\n", id); if (!micro->msg)
dev_info(micro->dev, "no message queued\n"); else
dev_info(micro->dev, "expected message %02x\n",
micro->msg->id);
} break; case MSG_KEYBOARD: if (micro->key)
micro->key(micro->key_data, len, data); else
dev_dbg(micro->dev, "key message ignored, no handle\n"); break; case MSG_TOUCHSCREEN: if (micro->ts)
micro->ts(micro->ts_data, len, data); else
dev_dbg(micro->dev, "touchscreen message ignored, no handle\n"); break; default:
dev_err(micro->dev, "unknown msg %d [%d] %*ph\n", id, len, len, data); break;
}
spin_unlock(µ->lock);
}
switch (rx->state) { case STATE_SOF: /* Looking for SOF */ if (ch == CHAR_SOF)
rx->state = STATE_ID; /* Next byte is the id and len */ break; case STATE_ID: /* Looking for id and len byte */
rx->id = (ch & 0xf0) >> 4;
rx->len = (ch & 0x0f);
rx->index = 0;
rx->chksum = ch;
rx->state = (rx->len > 0) ? STATE_DATA : STATE_CHKSUM; break; case STATE_DATA: /* Looking for 'len' data bytes */
rx->chksum += ch;
rx->buf[rx->index] = ch; if (++rx->index == rx->len)
rx->state = STATE_CHKSUM; break; case STATE_CHKSUM: /* Looking for the checksum */ if (ch == rx->chksum)
micro_rx_msg(micro, rx->id, rx->len, rx->buf);
rx->state = STATE_SOF; break;
}
}
staticint __init micro_probe(struct platform_device *pdev)
{ struct ipaq_micro *micro; int ret; int irq;
micro = devm_kzalloc(&pdev->dev, sizeof(*micro), GFP_KERNEL); if (!micro) return -ENOMEM;
micro->dev = &pdev->dev;
micro->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(micro->base)) return PTR_ERR(micro->base);
micro->sdlc = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(micro->sdlc)) return PTR_ERR(micro->sdlc);
micro_reset_comm(micro);
irq = platform_get_irq(pdev, 0); if (irq < 0) return -EINVAL;
ret = devm_request_irq(&pdev->dev, irq, micro_serial_isr,
IRQF_SHARED, "ipaq-micro",
micro); if (ret) {
dev_err(&pdev->dev, "unable to grab serial port IRQ\n"); return ret;
} else
dev_info(&pdev->dev, "grabbed serial port IRQ\n");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.