誰ãæ°ã«ããŸã-ç«ãžããããã
ç®æ¬¡ïŒ
- ééšåã®èª¬æ
- åé¡ã¯ã©ãã«ãããŸããïŒ
- ããã€ã¹ããªãŒã«ã€ããŠäžèš
- ããã€ã¹ãšãã©ã€ããŒã®ç»é²ã«ã€ããŠå°ã
- é 延ãã©ã€ããŒã®ããŒãã¡ã«ããºã
- ãã¹ãŠãæ©èœãããæ¹æ³
ããŒããŒãã®åšãã®éã®èª¬æïŒ
ã³ã³ãããŒã©ãŒèªäœã®ããŒããŒãã«ã¯ãããŸãã-ç¹å¥ãªãããªãã¯ã¹ããŒããŒãã³ã³ãããŒã©ãŒ-adp5589ãããã䜿çšããŠI2Cãã¹ãä»ããŠæ¥ç¶ãããŠããŸãã ãããã«ã¯ãARM SoC GPIOãã³ã®1ã€ã«å·»ãããå²ã蟌ã¿ã©ã€ã³ããããŸãã ãã®çµæãæ¥ç¶å³ã¯æ¬¡ã®ããã«ãªããŸãã
portbã¯ããã³ãããŒããŒãã³ã³ãããŒã©ãŒã«ãã£ãŠäžæãããããŒãã§ãã
intc-ã¡ã€ã³å²ã蟌ã¿ã³ã³ãããŒã©ãŒã
i2c0 - i2cãã¹ã³ã³ãããŒã©ãŒã
äœããã®çç±ã§adp5589ãã©ã€ããŒã¯ãé åºã«å²ã蟌ã¿çªå·ãååŸããããããŸããã ãã®åäœã®çç±ã¯äœã§ããããïŒ ããŒããŒããã©ã€ããŒãèªã¿èŸŒãããã®ãªãœãŒã¹ãäžè¶³ããŠããå¯èœæ§ããããŸãã äŸåããããã€ã¹ã«èµ·åããæéããªãã£ãã®ã§ããããïŒ äŸåã§ããããã€ã¹ãèŠãŠã¿ãŸãããã
ãŸããæ¥ç¶ãããŠããI2Cãã¹ã³ã³ãããŒã©ãŒããã
第äºã«-ããŒãã³ã³ãããŒã©ããããã³ã«å²ã蟌ã¿ã©ã€ã³ããããŸãã
次ã«ããããã®ããã€ã¹ã®ãã©ã€ããŒãããŒããããé çªãèŠãŠã¿ãŸãããã
ã®ãã¯
designware-i2c
adp5589
dw-apb-gpio-port
ããïŒ ãããçç±ã§ã-ããŒããŒããã©ã€ããŒãèªã¿èŸŒãŸãããšãããã®å²ã蟌ã¿èŠªã¯ãŸã èªã¿èŸŒãŸããŠããŸããã ãã®çµæãããŒããŒããã©ã€ããŒã¯å²ã蟌ã¿çªå·ãåãåããŸããã ãã®åé¡ã®æšæºçãªè§£æ±ºçã¯ããã©ã€ããŒã®é 延èªã¿èŸŒã¿ã¡ã«ããºã ã§ãã
ãã®æ¬è³ªã¯ãå¿ èŠãªãªãœãŒã¹ããŸã å©çšå¯èœã§ãªãå Žåããã©ã€ããŒããªããŒããå¿ èŠãšããå¯èœæ§ãããããšã§ãã ãããŠã圌ã¯ãããŒãé¢æ°ããå€-EPROBE_DEFERãè¿ãããšã§ãããèŠæ±ã§ããŸãã ãã®åŸããã®ãã©ã€ããŒã¯åŸã§ãªããŒããããŸãã ãã®æãŸã§ã«ãç®çã®ãªãœãŒã¹ããã§ã«å©çšå¯èœã«ãªã£ãŠãããããã©ã€ããŒã®ããŠã³ããŒããåã³é 延ããŸãã
ããŒããŒããã©ã€ããŒã®ãããŒããã©ã€ããŒæ©èœã«ãã¹ããè¿œå ããŸãã
if (!client->irq) { dev_err(&client->dev, "no IRQ boss?\n"); return -EPROBE_DEFER; }
æ°ããèµ·åé åºã確èªãããïŒ
ã®ãã¯
adp5589
designware-i2c
dw-apb-gpio-port
ïŒå»¶æïŒadp5589
ïŒå»¶æïŒadp5589
ïŒå»¶æïŒadp5589
äœãããããã-GPIOãã©ã€ããŒã®åŸã«ããŒããŒããã©ã€ããŒãåããŒããããããå²ã蟌ã¿ãåä¿¡ããªãã£ãã äºæ³ä»¥äžã«ãœãŒã¹ã³ãŒããæ·±ãæãäžããå¿ èŠãããããã§ãã
次ã®3ã€ã®è§£æ±ºçããããŸãã
- å²ã蟌ã¿çªå·ãçŽæ¥ãã©ã€ããŒã«ããŒãã³ãŒããã
- äœããã®æ¹æ³ã§ããã©ã€ããŒã®èµ·åé åºãèšå®ããŸã
- äœããã®çç±ã§æ©èœããªãã£ãããã©ã€ããŒã®é 延èªã¿èŸŒã¿ã®ã¡ã«ããºã ã«å¯ŸåŠãã
æåã®ãªãã·ã§ã³ïŒ
ãã®ãªãã·ã§ã³ã¯æ©èœããŠããŸãããæãŸãããããŸããã äžæçãªãã®ãšããŠé©ããŠããŸãããããŒããŠã§ã¢ã§äœããå€æŽããå ŽåïŒããšãã°ãå²ã蟌ã¿åºåãå¥ã®GPIOããŒãã«æ¥ç¶ããå ŽåïŒãããã€ã¹ããªãŒã ãã§ãªãããã©ã€ããŒã®ãœãŒã¹ã³ãŒããå€æŽããå¿ èŠããããŸãã
2çªç®ã®ãªãã·ã§ã³ïŒ
ãã©ã€ããŒã®èµ·åé åºãæ瀺çã«èšå®ããããšã¯ã§ããŸããã ãããã£ãŠããã®ãªãã·ã§ã³ã¯é©åã§ã¯ãããŸããã
3çªç®ã®ãªãã·ã§ã³ïŒ
æãæ£ãããã®ã æ€èšããŸãã
ããã§ããããããããã€ã¹ããªãŒãªã©ã«ã€ããŠç°¡åã«èª¬æãã䟡å€ããããŸããããã«ã€ããŠã¯åŸã§åç §ããããã§ãã
ããã€ã¹ããªãŒã¯ãLinuxã䜿çšããããã€ã¹ã®ããŒããŠã§ã¢ãèšè¿°ãã圢åŒã§ãã ããã¯ãå¿ èŠãªæ å ±ãèšå®ãããŠããããŒãã®ããªãŒã®åœ¢åŒã§è¡šç€ºãããŸãã DTã¯ã人éãèªã¿åããããã¹ããã¡ã€ã«ïŒ .dts ; .dtsi ïŒãšããããããçµã¿ç«ãŠããããã€ããªãã¡ã€ã«ïŒ .dtb ïŒã®åœ¢åŒã§ååšããŸãã
ããšãã°ãããŒããŒãã³ã³ãããŒã©ãŒãšä»ã®SoCaããã€ã¹ã®æ¥ç¶æ§é ãèšè¿°ãã.dtsãã¡ã€ã«ã®äžéšãèããŠã¿ãŸãããã
i2c0: i2c@ffc04000 { compatible = "snps,designware-i2c"; keybs@34 { compatible = "adi,adp5589"; interrupts = <19 IRQ_TYPE_LEVEL_LOW>; interrupt-parent = <&portb>; }; }; intc: intc@fffed000 { compatible = "arm,cortex-a9-gic"; #interrupt-cells = <3>; interrupt-controller; }; portb: gpio-controller@0 { compatible = "snps,dw-apb-gpio-port"; interrupt-controller; #interrupt-cells = <2>; interrupts = <0 165 4>; interrupt-parent = <&intc>; };
ïŒç解ããããããã«ãçŸåšèå³ã®ãªãããŒããšããããã£ã¯çç¥ãããŠããŸãïŒ
i2c0 ã keybs ã incããã³portbã¯ããŒãã§ãããä»ã®ãã¹ãŠã¯ãããã®ããããã£ã§ãã ã³ãŒããããããŒããŒãã³ã³ãããŒã©ãŒããããI2Cãã¹ã«æ¥ç¶ãããŠããããšãããã«ããããŸãã compatibleããããã£ã§ãããã€ã¹ã®ã¡ãŒã«ãŒãšã¢ãã«ã説æããæååã OSããã®ããã€ã¹ã«é¢é£ä»ããå¿ èŠããããã©ã€ããŒãèªèããã®ã¯ããã®ããããã£ã®ããã§ãã
interrupt-controllerã¯ããã®ããã€ã¹ãå²ã蟌ã¿ã³ã³ãããŒã©ãŒã«ã§ããããšã瀺ãããããã£ã§ããã interrupt-parentã¯ãçŸåšã®ããã€ã¹ããã®å²ã蟌ã¿ã誰ã«æ¥ç¶ãããŠãããã瀺ããŸãã
ïŒinterrupt-cellsã¯ãç¹å®ã®å²ã蟌ã¿ã³ã³ãããŒã©ãŒã®å²ã蟌ã¿ãèšè¿°ãããã©ã¡ãŒã¿ãŒã®æ°ã瀺ãããããã£ã§ããã interruptsã¯ããã®å²ã蟌ã¿ã®ãã©ã¡ãŒã¿ãŒãèšå®ãããããããã£ã§ãã
ããšãã°ã portbã¯æ¬¡ã®ããã«è¿°ã¹ãŠããŸããïŒinterrupt-cells = <2>ããã¯ã portbãinterrupt-parentã§ããããŒãã§ã¯ã interruptsããããã£ã« 2ã€ã®ãã©ã¡ãŒã¿ãŒãèšè¿°ããå¿ èŠãããããšãæå³ããŸãã portbã¯keybsã®å²ã蟌ã¿èŠªã§ãã ç§ãã¡ã¯ããŒããŒãã調ã¹ãŸãã å²ã蟌ã¿= <19 IRQ_TYPE_LEVEL_LOW>ã瀺ããŸãã ããã¯ã©ãããæå³ã§ããïŒ
ããã§ã¯ã2ã€ã®ãã©ã¡ãŒã¿ãŒã«ã€ããŠèª¬æããŸãã 1ã€ç®ã¯ããŒãportã®ãã³çªå·ã§ãããŒããŒãã³ã³ãããŒã©ãŒããã®å²ã蟌ã¿ã©ã€ã³ããããŸãã 2çªç®ã¯ãå²ã蟌ã¿ã®ã¿ã€ãïŒäœãŸãã¯é«ïŒã§ãã å²ã蟌ã¿ã³ã³ãããŒã©ã®ãã©ã¡ãŒã¿ãããã€èšè¿°ããå¿ èŠãããã®ãââããŸãããããã®æå³ã¯ã©ã®ããã«ããããŸããïŒ éåžžãããã¯ããã¥ã¡ã³ãã«æžãããŠããŸãã ãããã£ãŠã portbã«ã€ããŠã¯ã次ã®ãã¡ã€ã«ã«èšè¿°ãããŠããŸãïŒ Documentation / devicetree / bindings / gpio / snps-dwapb-gpio.txt
ïŒportb - portbããŒããžã®ãªã³ã¯ïŒãã®å Žåãportbãžã®ãªã³ã¯ã¯/ soc / gpio @ ff709000 / gpio-controller @ 0ã«ãªããŸãïŒ
æ®ãã®ããããã£ã¯ãŸã å¿ èŠãããŸããããããã«ã€ããŠãããã³äžè¬çã«ããã€ã¹ããªãŒã«ã€ããŠã¯ã devicetree.org / Device_Tree_Usageã§è©³çŽ°ãèªãããšãã§ããŸãã
ããã€ã¹ãšãã©ã€ããŒãç»é²ããããã»ã¹ã«èšåããããšã¯äžå¿ èŠã§ã¯ãããŸããïŒå¿é ããªãã§ãã ããã次ã®æ®µèœã®ã¡ã€ã³ãããã¯ã«æ»ããŸãïŒã Linuxããã€ã¹ã¢ãã«ã«ãããšïŒ
ããã€ã¹ -ãã¹ã«æ¥ç¶ãããŠããç©çãªããžã§ã¯ããŸãã¯ä»®æ³ãªããžã§ã¯ãïŒããããä»®æ³ïŒ
ãã©ã€ããŒã¯ãããã€ã¹ã«æ¥ç¶ã§ããããããå¶åŸ¡æ©èœãå®è¡ã§ãããœãããŠã§ã¢ãªããžã§ã¯ãã§ãã
ãã¹ã¯ãä»ã®ããã€ã¹ã®ãæ¥ç¶ãã€ã³ããã«ãªãããã«èšèšãããããã€ã¹ã§ãã ã«ãŒãã«ããµããŒããããã¹ãŠã®ãã¹ã®åºæ¬æ©èœã¯ã bus_typeæ§é ã«ãã£ãŠæ±ºå®ãããŸãã ãã®æ§é ã§ã¯ããã¹ããããsubsys_privateæ§é ã宣èšããã2ã€ã®ãªã¹ãã宣èšãããŸãïŒ klist_devicesããã³klist_drivers ã
klist_devices-ãã¹ã«æ¥ç¶ãããŠããããã€ã¹ã®ãªã¹ãã
klist_drivers-ãã®ãã¹äžã®ããã€ã¹ãå¶åŸ¡ã§ãããã©ã€ããŒã®ãªã¹ãã
device_registerããã³driver_registeré¢æ°ã䜿çšããŠãããã€ã¹ãšãã©ã€ããŒããããã®ãªã¹ãã«è¿œå ãããŸã ã ããã«ã device_registerããã³driver_registerã¯ãããã€ã¹ãé©åãªãã©ã€ããŒã«é¢é£ä»ããŸãã device_registerã¯ããã©ã€ããŒã®ãªã¹ãã調ã¹ãŠããã®ããã€ã¹ã«é©ãããã©ã€ããŒãèŠã€ããããšããŸãã ïŒ driver_registerã¯ããã€ã¹ã®ãªã¹ãã調ã¹ãŠã管çã§ããããã€ã¹ãèŠã€ããããšããŸãïŒãã©ã€ããŒãããã€ã¹ã«é©ããŠãããã©ããã®ç¢ºèªã¯ã bus_typeæ§é äœãžã®ãã€ã³ã¿ãŒã§ããmatch ïŒdevãdrvïŒé¢æ°ã䜿çšããŠè¡ãããŸãã
ããã§ãã¡ã€ã³ãããã¯-é 延ãã©ã€ããŒã®ããŒãã¡ã«ããºã ã®å®è£ ã«é²ã¿ãŸãã drivers / base / dd.cãã¡ã€ã«ãèŠãŠã¿ãŸãããã
ãã©ã€ãã®ãªããŒããå¶åŸ¡ããããã®2ã€ã®ãªã¹ã-deferred_probe_pending_listãšdeferred_probe_active_listããããŸãã
deferred_probe_pending_list-ãã©ã€ããŒã«ãªãœãŒã¹ãäžè¶³ããŠããããã€ã¹ã®ãªã¹ãã
deferred_probe_active_list-ãã©ã€ããŒãåèµ·åã§ããããã€ã¹ã®ãªã¹ãã
really_probeé¢æ°ã¯ãããã€ã¹ãé 眮ãããŠãããã¹ã®ãããŒãé¢æ°ãåŒã³åºããŸãã ç§ãã¡ã®å Žåãããã¯é¢æ°i2c_device_probe㧠ããã®dev- > bus- > probeïŒdevïŒã®ããã«èŠããŸãã æ»ãå€ã®ãšã©ãŒããã§ãã¯ããã -EPROBE_DEFERã®å Žåãããã€ã¹ã¯deferred_probe_pending_listã«è¿œå ãããŸãã
ããããæãèå³æ·±ãã®ã¯ããã©ã€ããŒããã€ã©ã®ããã«åŒã³åºããããã§ãã ãã©ã€ããŒã-EPROBE_DEFERãè¿ãé ãããã€ã¹ã¯deferred_probe_pending_listã«é 次远å ãããŸãã ãã ãããããŒãæ©èœããã©ã€ããŒã«å¯ŸããŠæåãããšã deferred_probe_pending_listã®ãã¹ãŠã®ããã€ã¹ãdeferred_probe_active_listã«è»¢éãããŸãã è«ççã«èŠããŸããæåŸã«æ£åžžã«ããŒããããã©ã€ããŒããä¿çäžã®ãã©ã€ããŒã®éåžžã®ããŒãã«ã¯äžååã ã£ãå¯èœæ§ããããŸãã deferred_probe_active_listãããã©ã€ããŒãéå§ãã2åç®ã®è©Šè¡ã¯ ã deferred_probe_work_funcé¢æ°ã«ãã£ãŠè¡ãããŸãã ãªã¹ãå ã®åããã€ã¹ã«å¯ŸããŠbus_probe_deviceãåŒã³åºããŸãã
bus_probe_deviceãåŒã³åºããšãæçµçã«ã¯ãããã€ã¹ãšãã®ãã©ã€ããŒãããã¢ã®really_probeé¢æ°ã«æ»ããŸãïŒäžèšãåç §ïŒã
ããããåŸ ã£ãŠãã ããïŒ çŸåšãããã€ã¹ãé 眮ãããŠãããã¹ã«å¯ŸããŠãããŒãé¢æ°ãåŒã³åºãããšã«ã€ããŠè©±ããŠããŸãã ããã¯i2c_device_probeã«ã€ããŠã§ã ã ããããããŒããŒãã®ãããŒããã©ã€ããŒæ©èœã¯ã©ãã§ããããã ããããå¿ããŠã¯ããŸãããi2c_device_probeããåŒã³åºãããã ãã§ã ã ããã確èªããã«ã¯ã drivers / i2c / i2c-core.cãã¡ã€ã«ã§ã³ãŒãã確èªããŸã ã
I2c_device_probeã³ãŒã
static int i2c_device_probe(struct device *dev) { struct i2c_client *client = i2c_verify_client(dev); struct i2c_driver *driver; int status; if (!client) return 0; driver = to_i2c_driver(dev->driver); if (!driver->probe || !driver->id_table) return -ENODEV; if (!device_can_wakeup(&client->dev)) device_init_wakeup(&client->dev, client->flags & I2C_CLIENT_WAKE); dev_dbg(dev, "probe\n"); status = of_clk_set_defaults(dev->of_node, false); if (status < 0) return status; status = dev_pm_domain_attach(&client->dev, true); if (status != -EPROBE_DEFER) { // probe ( ) status = driver->probe(client, i2c_match_id(driver->id_table, client)); if (status) dev_pm_domain_detach(&client->dev, true); } return status; }
ããŠããªããŒãã¯æ©èœããŠããããã«æããŸãããããŒããŒããã©ã€ããŒãå²ã蟌ã¿çªå·ãååŸããªãã®ã¯ãªãã§ããïŒ
å²ã蟌ã¿çªå·ãã©ã®ããã«ãã©ã€ããŒã«å ¥ããã远跡ããŠã¿ãŸãããã
ã¯ã©ã€ã¢ã³ãæ§é ã¯adp5589_probeé¢æ°ïŒstruct i2c_client * clientãconst struct i2c_device_id * idïŒã«æž¡ããããã®ãã£ãŒã«ãã®1ã€ã¯irq-ããã€ã¹ïŒããŒããŒãã³ã³ãããŒã©ãŒïŒãçæããå²ã蟌ã¿çªå·ã§ãã adp5589_probe㯠ã i2c_device_probeé¢æ°ïŒstruct device * devïŒããåŒã³åºãããŸãã ããã€ã¹æ§é ã¯ã i2c_clientæ§é ãžã®ãã€ã³ã¿ãŒãèšç®ããããã€ã³ã¿ãŒããïŒ container_ofãã¯ã
container_ofã«ã€ããŠäžèš
ãã®ãã¯ãã¯ãæ§é äœãã£ãŒã«ããžã®ãã€ã³ã¿ãŒãžã®å
¥åããã®æ§é äœã®ã¿ã€ããããã³ãã€ã³ã¿ãŒãæããã£ãŒã«ãã®ååãåãåããæ§é äœèªäœãžã®ãã€ã³ã¿ãŒãè¿ããŸãã
圌ã®ä»äºã«ã€ããŠã¯ããã§ããæãããŠããŸã ã
圌ã®ä»äºã«ã€ããŠã¯ããã§ããæãããŠããŸã ã
ãã®ããã i2c_clientæ§é äœãé 眮ãããŠããå ŽæãèŠã€ããå¿ èŠããããŸãã é¢æ°i2c_new_device ïŒstruct i2c_adapter * adapãstruct i2c_board_info const * infoïŒã«å ¥åãããŸãã å ·äœçã«ã¯ãirqãã£ãŒã«ãã¯i2c_board_infoæ§é äœã®åããã£ãŒã«ãããã³ããŒãããŸãã
struct i2c_client *client; client->irq = info->irq;
i2c_board_infoæ§é äœã¯ ã of_i2c_register_devicesé¢æ°ïŒstruct i2c_adapter * adapïŒã«å ¥åãããŸãã
info.irq = irq_of_parse_and_map(node, 0);
irq_of_parse_and_mapã¯ã of_irq_parse_oneãširq_create_of_mappingã® 2ã€ã®é¢æ°ã®ãã§ãŒã³ã®ã©ãããŒã§ãã of_irq_parse_oneé¢æ°ã¯ãçŸåšã®ããã€ã¹ã®å²ã蟌ã¿ã³ã³ãããŒã©ãŒãšããŠããã€ã¹ããªãŒã§å®£èšãããŠããããŒããèŠã€ããããšããŸãã
ããã€ã¹ããªãŒã®ãããã®æ°è¡ãèŠããŠããŸããïŒ
expander: pca9535@20 { interrupt-parent = <&portb>; };
of_irq_parse_oneãæ€çŽ¢ããã®ã¯portbã§ããããã®äœæ¥çµæã«å¿ããŠã irq_create_of_mappingé¢æ°ã«æž¡ãããæ§é äœof_phandle_argsãåããŸãã irq_create_of_mappingã¯æ¢ã«ãããç®çã®å²ã蟌ã¿çªå·ãè¿ããŸãã
åããŠã of_irq_parse_oneã¯ãã°ã§èªãGPIOããŒããèŠã€ããŸããã
irqïŒ/ soc / gpio @ ff709000 / gpio-controller @ 0ã®irqãã¡ã€ã³ãèŠã€ãããŸããïŒ
ãããŠããã©ã€ããŒããªããŒãããããšã©ããªããŸããïŒ ããããäœãã i2c_device_probeãšadp5589_probeã®ã¿ãåŒã³åºãããŸãã
ãããåé¡ã§ãã å²ã蟌ã¿ã¯åããŠã€ã³ã¹ããŒã«ããããã©ã€ããŒãã©ãã ããªããŒãããŠããæ°žä¹ ã«æ®ããŸãã
åé¡ãèŠã€ãããŸãããããããä¿®æ£ããæ¹æ³ã¯ïŒ
å²ã蟌ã¿ã³ãŒããi2c_device_probeã«è»¢éããŠã¿ãŠãã ããã ãã以åã¯ãã©ãã«ãå²ã蟌ã¿çªå·ã¯å¿ èŠãªããããåé¡ã¯ãªãã¯ãã§ãã
ããããããè¯ãã®ã¯ãã«ãŒãã«ã®ææ°ããŒãžã§ã³ïŒããŒãžã§ã³3.18ãã€ã³ã¹ããŒã«ãããŠããïŒã®ãœãŒã¹ã調ã¹ãŠã¿ãŸãããã
ã¯ã©ã€ã¢ã³ãi2cå²ã蟌ã¿ã®èšå®ã¯ã i2c_device_probeé¢æ°ã«è»¢éãããŸããã
if (!client->irq && dev->of_node) { int irq = of_irq_get(dev->of_node, 0); if (irq == -EPROBE_DEFER) return irq; if (irq < 0) irq = 0; client->irq = irq; }
irqãã£ãŒã«ãã¯i2c_board_infoæ§é ã«æ®ããŸããã䜿çšãããŸããã ãã®ãããã«ãŒãã«ã®æ°ããããŒãžã§ã³ã§ã¯ãåé¡ã¯ä¿®æ£ãããŠããŸãã
å€æŽãããŒãžã§ã³ã«è»¢éããã ãã§ãã ãã¹ãŠã®å€æŽã¯ããã¡ã€ã«ãã©ã€ããŒ/ i2c / i2c-core.cã«åœ±é¿ããŸã
i2cã¯ã©ã€ã¢ã³ãã®å²ã蟌ã¿èšå®ãi2c_device_probeã«è¿œå ããŸããããã¯ææ°ããŒãžã§ã³ã«ããã of_i2c_register_devicesé¢æ°ã®å²ã蟌ã¿èšå®ãåé€ããŸãã
git diffããã®å€æŽã®ãªã¹ã
--- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -626,6 +626,17 @@ static int i2c_device_probe(struct device *dev) if (!client) return 0; + if (!client->irq && dev->of_node) { + int irq = of_irq_get(dev->of_node, 0); + + if (irq == -EPROBE_DEFER) + return irq; + if (irq < 0) + irq = 0; + + client->irq = irq; + } + driver = to_i2c_driver(dev->driver); if (!driver->probe || !driver->id_table) return -ENODEV; @@ -1407,7 +1418,12 @@ static void of_i2c_register_devices(struct i2c_adapter *adap) continue; } - info.irq = irq_of_parse_and_map(node, 0); + /* + * Now, we don't need to set interrupt here, because we set + * it in i2c_device_probe function + * info.irq = irq_of_parse_and_map(node, 0); + */ + info.of_node = of_node_get(node); info.archdata = &dev_ad;
ãã§ãã¯-ããŒããŒãã¯æ©èœããŠããŸãã / proc / interruptã調ã¹ãŸãã
$ grep 'adp5589_keys' /proc/interrupts 305: 2 - 20 adp5589_keys
ããã€ãã®ãã¿ã³ãæŒããŸãã
$ grep 'adp5589_keys' /proc/interrupts 305: 6 - 20 adp5589_keys
åé¡ã¯è§£æ±ºããŸããã