diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-eg20t.c')
-rw-r--r-- | drivers/i2c/busses/i2c-eg20t.c | 161 |
1 files changed, 99 insertions, 62 deletions
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c index 50ea1f43bdc1..878a12026af2 100644 --- a/drivers/i2c/busses/i2c-eg20t.c +++ b/drivers/i2c/busses/i2c-eg20t.c | |||
@@ -132,6 +132,13 @@ | |||
132 | #define pch_pci_dbg(pdev, fmt, arg...) \ | 132 | #define pch_pci_dbg(pdev, fmt, arg...) \ |
133 | dev_dbg(&pdev->dev, "%s :" fmt, __func__, ##arg) | 133 | dev_dbg(&pdev->dev, "%s :" fmt, __func__, ##arg) |
134 | 134 | ||
135 | /* | ||
136 | Set the number of I2C instance max | ||
137 | Intel EG20T PCH : 1ch | ||
138 | OKI SEMICONDUCTOR ML7213 IOH : 2ch | ||
139 | */ | ||
140 | #define PCH_I2C_MAX_DEV 2 | ||
141 | |||
135 | /** | 142 | /** |
136 | * struct i2c_algo_pch_data - for I2C driver functionalities | 143 | * struct i2c_algo_pch_data - for I2C driver functionalities |
137 | * @pch_adapter: stores the reference to i2c_adapter structure | 144 | * @pch_adapter: stores the reference to i2c_adapter structure |
@@ -156,12 +163,14 @@ struct i2c_algo_pch_data { | |||
156 | * @pch_data: stores a list of i2c_algo_pch_data | 163 | * @pch_data: stores a list of i2c_algo_pch_data |
157 | * @pch_i2c_suspended: specifies whether the system is suspended or not | 164 | * @pch_i2c_suspended: specifies whether the system is suspended or not |
158 | * perhaps with more lines and words. | 165 | * perhaps with more lines and words. |
166 | * @ch_num: specifies the number of i2c instance | ||
159 | * | 167 | * |
160 | * pch_data has as many elements as maximum I2C channels | 168 | * pch_data has as many elements as maximum I2C channels |
161 | */ | 169 | */ |
162 | struct adapter_info { | 170 | struct adapter_info { |
163 | struct i2c_algo_pch_data pch_data; | 171 | struct i2c_algo_pch_data pch_data[PCH_I2C_MAX_DEV]; |
164 | bool pch_i2c_suspended; | 172 | bool pch_i2c_suspended; |
173 | int ch_num; | ||
165 | }; | 174 | }; |
166 | 175 | ||
167 | 176 | ||
@@ -170,8 +179,13 @@ static int pch_clk = 50000; /* specifies I2C clock speed in KHz */ | |||
170 | static wait_queue_head_t pch_event; | 179 | static wait_queue_head_t pch_event; |
171 | static DEFINE_MUTEX(pch_mutex); | 180 | static DEFINE_MUTEX(pch_mutex); |
172 | 181 | ||
182 | /* Definition for ML7213 by OKI SEMICONDUCTOR */ | ||
183 | #define PCI_VENDOR_ID_ROHM 0x10DB | ||
184 | #define PCI_DEVICE_ID_ML7213_I2C 0x802D | ||
185 | |||
173 | static struct pci_device_id __devinitdata pch_pcidev_id[] = { | 186 | static struct pci_device_id __devinitdata pch_pcidev_id[] = { |
174 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_I2C)}, | 187 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_I2C), 1, }, |
188 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_I2C), 2, }, | ||
175 | {0,} | 189 | {0,} |
176 | }; | 190 | }; |
177 | 191 | ||
@@ -212,8 +226,7 @@ static void pch_i2c_init(struct i2c_algo_pch_data *adap) | |||
212 | /* Initialize I2C registers */ | 226 | /* Initialize I2C registers */ |
213 | iowrite32(0x21, p + PCH_I2CNF); | 227 | iowrite32(0x21, p + PCH_I2CNF); |
214 | 228 | ||
215 | pch_setbit(adap->pch_base_address, PCH_I2CCTL, | 229 | pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_I2CCTL_I2CMEN); |
216 | PCH_I2CCTL_I2CMEN); | ||
217 | 230 | ||
218 | if (pch_i2c_speed != 400) | 231 | if (pch_i2c_speed != 400) |
219 | pch_i2c_speed = 100; | 232 | pch_i2c_speed = 100; |
@@ -255,7 +268,7 @@ static inline bool ktime_lt(const ktime_t cmp1, const ktime_t cmp2) | |||
255 | * @timeout: waiting time counter (us). | 268 | * @timeout: waiting time counter (us). |
256 | */ | 269 | */ |
257 | static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap, | 270 | static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap, |
258 | s32 timeout) | 271 | s32 timeout) |
259 | { | 272 | { |
260 | void __iomem *p = adap->pch_base_address; | 273 | void __iomem *p = adap->pch_base_address; |
261 | 274 | ||
@@ -475,8 +488,8 @@ static void pch_i2c_sendnack(struct i2c_algo_pch_data *adap) | |||
475 | * @last: specifies whether last message or not. | 488 | * @last: specifies whether last message or not. |
476 | * @first: specifies whether first message or not. | 489 | * @first: specifies whether first message or not. |
477 | */ | 490 | */ |
478 | s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, | 491 | static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, |
479 | u32 last, u32 first) | 492 | u32 last, u32 first) |
480 | { | 493 | { |
481 | struct i2c_algo_pch_data *adap = i2c_adap->algo_data; | 494 | struct i2c_algo_pch_data *adap = i2c_adap->algo_data; |
482 | 495 | ||
@@ -569,10 +582,10 @@ s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, | |||
569 | } | 582 | } |
570 | 583 | ||
571 | /** | 584 | /** |
572 | * pch_i2c_cb_ch0() - Interrupt handler Call back function | 585 | * pch_i2c_cb() - Interrupt handler Call back function |
573 | * @adap: Pointer to struct i2c_algo_pch_data. | 586 | * @adap: Pointer to struct i2c_algo_pch_data. |
574 | */ | 587 | */ |
575 | static void pch_i2c_cb_ch0(struct i2c_algo_pch_data *adap) | 588 | static void pch_i2c_cb(struct i2c_algo_pch_data *adap) |
576 | { | 589 | { |
577 | u32 sts; | 590 | u32 sts; |
578 | void __iomem *p = adap->pch_base_address; | 591 | void __iomem *p = adap->pch_base_address; |
@@ -600,24 +613,30 @@ static void pch_i2c_cb_ch0(struct i2c_algo_pch_data *adap) | |||
600 | */ | 613 | */ |
601 | static irqreturn_t pch_i2c_handler(int irq, void *pData) | 614 | static irqreturn_t pch_i2c_handler(int irq, void *pData) |
602 | { | 615 | { |
603 | s32 reg_val; | 616 | u32 reg_val; |
604 | 617 | int flag; | |
605 | struct i2c_algo_pch_data *adap_data = (struct i2c_algo_pch_data *)pData; | 618 | int i; |
606 | void __iomem *p = adap_data->pch_base_address; | 619 | struct adapter_info *adap_info = pData; |
607 | u32 mode = ioread32(p + PCH_I2CMOD) & (BUFFER_MODE | EEPROM_SR_MODE); | 620 | void __iomem *p; |
608 | 621 | u32 mode; | |
609 | if (mode != NORMAL_MODE) { | 622 | |
610 | pch_err(adap_data, "I2C mode is not supported\n"); | 623 | for (i = 0, flag = 0; i < adap_info->ch_num; i++) { |
611 | return IRQ_NONE; | 624 | p = adap_info->pch_data[i].pch_base_address; |
625 | mode = ioread32(p + PCH_I2CMOD); | ||
626 | mode &= BUFFER_MODE | EEPROM_SR_MODE; | ||
627 | if (mode != NORMAL_MODE) { | ||
628 | pch_err(adap_info->pch_data, | ||
629 | "I2C-%d mode(%d) is not supported\n", mode, i); | ||
630 | continue; | ||
631 | } | ||
632 | reg_val = ioread32(p + PCH_I2CSR); | ||
633 | if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT)) { | ||
634 | pch_i2c_cb(&adap_info->pch_data[i]); | ||
635 | flag = 1; | ||
636 | } | ||
612 | } | 637 | } |
613 | 638 | ||
614 | reg_val = ioread32(p + PCH_I2CSR); | 639 | return flag ? IRQ_HANDLED : IRQ_NONE; |
615 | if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT)) | ||
616 | pch_i2c_cb_ch0(adap_data); | ||
617 | else | ||
618 | return IRQ_NONE; | ||
619 | |||
620 | return IRQ_HANDLED; | ||
621 | } | 640 | } |
622 | 641 | ||
623 | /** | 642 | /** |
@@ -627,7 +646,7 @@ static irqreturn_t pch_i2c_handler(int irq, void *pData) | |||
627 | * @num: number of messages. | 646 | * @num: number of messages. |
628 | */ | 647 | */ |
629 | static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap, | 648 | static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap, |
630 | struct i2c_msg *msgs, s32 num) | 649 | struct i2c_msg *msgs, s32 num) |
631 | { | 650 | { |
632 | struct i2c_msg *pmsg; | 651 | struct i2c_msg *pmsg; |
633 | u32 i = 0; | 652 | u32 i = 0; |
@@ -710,11 +729,13 @@ static void pch_i2c_disbl_int(struct i2c_algo_pch_data *adap) | |||
710 | } | 729 | } |
711 | 730 | ||
712 | static int __devinit pch_i2c_probe(struct pci_dev *pdev, | 731 | static int __devinit pch_i2c_probe(struct pci_dev *pdev, |
713 | const struct pci_device_id *id) | 732 | const struct pci_device_id *id) |
714 | { | 733 | { |
715 | void __iomem *base_addr; | 734 | void __iomem *base_addr; |
716 | s32 ret; | 735 | int ret; |
736 | int i, j; | ||
717 | struct adapter_info *adap_info; | 737 | struct adapter_info *adap_info; |
738 | struct i2c_adapter *pch_adap; | ||
718 | 739 | ||
719 | pch_pci_dbg(pdev, "Entered.\n"); | 740 | pch_pci_dbg(pdev, "Entered.\n"); |
720 | 741 | ||
@@ -744,44 +765,48 @@ static int __devinit pch_i2c_probe(struct pci_dev *pdev, | |||
744 | goto err_pci_iomap; | 765 | goto err_pci_iomap; |
745 | } | 766 | } |
746 | 767 | ||
747 | adap_info->pch_i2c_suspended = false; | 768 | /* Set the number of I2C channel instance */ |
769 | adap_info->ch_num = id->driver_data; | ||
748 | 770 | ||
749 | adap_info->pch_data.p_adapter_info = adap_info; | 771 | for (i = 0; i < adap_info->ch_num; i++) { |
772 | pch_adap = &adap_info->pch_data[i].pch_adapter; | ||
773 | adap_info->pch_i2c_suspended = false; | ||
750 | 774 | ||
751 | adap_info->pch_data.pch_adapter.owner = THIS_MODULE; | 775 | adap_info->pch_data[i].p_adapter_info = adap_info; |
752 | adap_info->pch_data.pch_adapter.class = I2C_CLASS_HWMON; | ||
753 | strcpy(adap_info->pch_data.pch_adapter.name, KBUILD_MODNAME); | ||
754 | adap_info->pch_data.pch_adapter.algo = &pch_algorithm; | ||
755 | adap_info->pch_data.pch_adapter.algo_data = | ||
756 | &adap_info->pch_data; | ||
757 | 776 | ||
758 | /* (i * 0x80) + base_addr; */ | 777 | pch_adap->owner = THIS_MODULE; |
759 | adap_info->pch_data.pch_base_address = base_addr; | 778 | pch_adap->class = I2C_CLASS_HWMON; |
779 | strcpy(pch_adap->name, KBUILD_MODNAME); | ||
780 | pch_adap->algo = &pch_algorithm; | ||
781 | pch_adap->algo_data = &adap_info->pch_data[i]; | ||
760 | 782 | ||
761 | adap_info->pch_data.pch_adapter.dev.parent = &pdev->dev; | 783 | /* base_addr + offset; */ |
784 | adap_info->pch_data[i].pch_base_address = base_addr + 0x100 * i; | ||
762 | 785 | ||
763 | ret = i2c_add_adapter(&(adap_info->pch_data.pch_adapter)); | 786 | pch_adap->dev.parent = &pdev->dev; |
764 | 787 | ||
765 | if (ret) { | 788 | ret = i2c_add_adapter(pch_adap); |
766 | pch_pci_err(pdev, "i2c_add_adapter FAILED\n"); | 789 | if (ret) { |
767 | goto err_i2c_add_adapter; | 790 | pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i); |
768 | } | 791 | goto err_i2c_add_adapter; |
792 | } | ||
769 | 793 | ||
770 | pch_i2c_init(&adap_info->pch_data); | 794 | pch_i2c_init(&adap_info->pch_data[i]); |
795 | } | ||
771 | ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED, | 796 | ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED, |
772 | KBUILD_MODNAME, &adap_info->pch_data); | 797 | KBUILD_MODNAME, adap_info); |
773 | if (ret) { | 798 | if (ret) { |
774 | pch_pci_err(pdev, "request_irq FAILED\n"); | 799 | pch_pci_err(pdev, "request_irq FAILED\n"); |
775 | goto err_request_irq; | 800 | goto err_i2c_add_adapter; |
776 | } | 801 | } |
777 | 802 | ||
778 | pci_set_drvdata(pdev, adap_info); | 803 | pci_set_drvdata(pdev, adap_info); |
779 | pch_pci_dbg(pdev, "returns %d.\n", ret); | 804 | pch_pci_dbg(pdev, "returns %d.\n", ret); |
780 | return 0; | 805 | return 0; |
781 | 806 | ||
782 | err_request_irq: | ||
783 | i2c_del_adapter(&(adap_info->pch_data.pch_adapter)); | ||
784 | err_i2c_add_adapter: | 807 | err_i2c_add_adapter: |
808 | for (j = 0; j < i; j++) | ||
809 | i2c_del_adapter(&adap_info->pch_data[j].pch_adapter); | ||
785 | pci_iounmap(pdev, base_addr); | 810 | pci_iounmap(pdev, base_addr); |
786 | err_pci_iomap: | 811 | err_pci_iomap: |
787 | pci_release_regions(pdev); | 812 | pci_release_regions(pdev); |
@@ -794,17 +819,22 @@ err_pci_enable: | |||
794 | 819 | ||
795 | static void __devexit pch_i2c_remove(struct pci_dev *pdev) | 820 | static void __devexit pch_i2c_remove(struct pci_dev *pdev) |
796 | { | 821 | { |
822 | int i; | ||
797 | struct adapter_info *adap_info = pci_get_drvdata(pdev); | 823 | struct adapter_info *adap_info = pci_get_drvdata(pdev); |
798 | 824 | ||
799 | pch_i2c_disbl_int(&adap_info->pch_data); | 825 | free_irq(pdev->irq, adap_info); |
800 | free_irq(pdev->irq, &adap_info->pch_data); | ||
801 | i2c_del_adapter(&(adap_info->pch_data.pch_adapter)); | ||
802 | 826 | ||
803 | if (adap_info->pch_data.pch_base_address) { | 827 | for (i = 0; i < adap_info->ch_num; i++) { |
804 | pci_iounmap(pdev, adap_info->pch_data.pch_base_address); | 828 | pch_i2c_disbl_int(&adap_info->pch_data[i]); |
805 | adap_info->pch_data.pch_base_address = 0; | 829 | i2c_del_adapter(&adap_info->pch_data[i].pch_adapter); |
806 | } | 830 | } |
807 | 831 | ||
832 | if (adap_info->pch_data[0].pch_base_address) | ||
833 | pci_iounmap(pdev, adap_info->pch_data[0].pch_base_address); | ||
834 | |||
835 | for (i = 0; i < adap_info->ch_num; i++) | ||
836 | adap_info->pch_data[i].pch_base_address = 0; | ||
837 | |||
808 | pci_set_drvdata(pdev, NULL); | 838 | pci_set_drvdata(pdev, NULL); |
809 | 839 | ||
810 | pci_release_regions(pdev); | 840 | pci_release_regions(pdev); |
@@ -817,17 +847,22 @@ static void __devexit pch_i2c_remove(struct pci_dev *pdev) | |||
817 | static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state) | 847 | static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state) |
818 | { | 848 | { |
819 | int ret; | 849 | int ret; |
850 | int i; | ||
820 | struct adapter_info *adap_info = pci_get_drvdata(pdev); | 851 | struct adapter_info *adap_info = pci_get_drvdata(pdev); |
821 | void __iomem *p = adap_info->pch_data.pch_base_address; | 852 | void __iomem *p = adap_info->pch_data[0].pch_base_address; |
822 | 853 | ||
823 | adap_info->pch_i2c_suspended = true; | 854 | adap_info->pch_i2c_suspended = true; |
824 | 855 | ||
825 | while ((adap_info->pch_data.pch_i2c_xfer_in_progress)) { | 856 | for (i = 0; i < adap_info->ch_num; i++) { |
826 | /* Wait until all channel transfers are completed */ | 857 | while ((adap_info->pch_data[i].pch_i2c_xfer_in_progress)) { |
827 | msleep(20); | 858 | /* Wait until all channel transfers are completed */ |
859 | msleep(20); | ||
860 | } | ||
828 | } | 861 | } |
862 | |||
829 | /* Disable the i2c interrupts */ | 863 | /* Disable the i2c interrupts */ |
830 | pch_i2c_disbl_int(&adap_info->pch_data); | 864 | for (i = 0; i < adap_info->ch_num; i++) |
865 | pch_i2c_disbl_int(&adap_info->pch_data[i]); | ||
831 | 866 | ||
832 | pch_pci_dbg(pdev, "I2CSR = %x I2CBUFSTA = %x I2CESRSTA = %x " | 867 | pch_pci_dbg(pdev, "I2CSR = %x I2CBUFSTA = %x I2CESRSTA = %x " |
833 | "invoked function pch_i2c_disbl_int successfully\n", | 868 | "invoked function pch_i2c_disbl_int successfully\n", |
@@ -850,6 +885,7 @@ static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state) | |||
850 | 885 | ||
851 | static int pch_i2c_resume(struct pci_dev *pdev) | 886 | static int pch_i2c_resume(struct pci_dev *pdev) |
852 | { | 887 | { |
888 | int i; | ||
853 | struct adapter_info *adap_info = pci_get_drvdata(pdev); | 889 | struct adapter_info *adap_info = pci_get_drvdata(pdev); |
854 | 890 | ||
855 | pci_set_power_state(pdev, PCI_D0); | 891 | pci_set_power_state(pdev, PCI_D0); |
@@ -862,7 +898,8 @@ static int pch_i2c_resume(struct pci_dev *pdev) | |||
862 | 898 | ||
863 | pci_enable_wake(pdev, PCI_D3hot, 0); | 899 | pci_enable_wake(pdev, PCI_D3hot, 0); |
864 | 900 | ||
865 | pch_i2c_init(&adap_info->pch_data); | 901 | for (i = 0; i < adap_info->ch_num; i++) |
902 | pch_i2c_init(&adap_info->pch_data[i]); | ||
866 | 903 | ||
867 | adap_info->pch_i2c_suspended = false; | 904 | adap_info->pch_i2c_suspended = false; |
868 | 905 | ||
@@ -894,7 +931,7 @@ static void __exit pch_pci_exit(void) | |||
894 | } | 931 | } |
895 | module_exit(pch_pci_exit); | 932 | module_exit(pch_pci_exit); |
896 | 933 | ||
897 | MODULE_DESCRIPTION("PCH I2C PCI Driver"); | 934 | MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH I2C Driver"); |
898 | MODULE_LICENSE("GPL"); | 935 | MODULE_LICENSE("GPL"); |
899 | MODULE_AUTHOR("Tomoya MORINAGA. <tomoya-linux@dsn.okisemi.com>"); | 936 | MODULE_AUTHOR("Tomoya MORINAGA. <tomoya-linux@dsn.okisemi.com>"); |
900 | module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR)); | 937 | module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR)); |