i2c-hydra.c (3462B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 i2c Support for the Apple `Hydra' Mac I/O 4 5 Copyright (c) 1999-2004 Geert Uytterhoeven <geert@linux-m68k.org> 6 7 Based on i2c Support for Via Technologies 82C586B South Bridge 8 Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi> 9 10*/ 11 12#include <linux/kernel.h> 13#include <linux/module.h> 14#include <linux/pci.h> 15#include <linux/types.h> 16#include <linux/i2c.h> 17#include <linux/i2c-algo-bit.h> 18#include <linux/io.h> 19#include <asm/hydra.h> 20 21 22#define HYDRA_CPD_PD0 0x00000001 /* CachePD lines */ 23#define HYDRA_CPD_PD1 0x00000002 24#define HYDRA_CPD_PD2 0x00000004 25#define HYDRA_CPD_PD3 0x00000008 26 27#define HYDRA_SCLK HYDRA_CPD_PD0 28#define HYDRA_SDAT HYDRA_CPD_PD1 29#define HYDRA_SCLK_OE 0x00000010 30#define HYDRA_SDAT_OE 0x00000020 31 32static inline void pdregw(void *data, u32 val) 33{ 34 struct Hydra *hydra = (struct Hydra *)data; 35 writel(val, &hydra->CachePD); 36} 37 38static inline u32 pdregr(void *data) 39{ 40 struct Hydra *hydra = (struct Hydra *)data; 41 return readl(&hydra->CachePD); 42} 43 44static void hydra_bit_setscl(void *data, int state) 45{ 46 u32 val = pdregr(data); 47 if (state) 48 val &= ~HYDRA_SCLK_OE; 49 else { 50 val &= ~HYDRA_SCLK; 51 val |= HYDRA_SCLK_OE; 52 } 53 pdregw(data, val); 54} 55 56static void hydra_bit_setsda(void *data, int state) 57{ 58 u32 val = pdregr(data); 59 if (state) 60 val &= ~HYDRA_SDAT_OE; 61 else { 62 val &= ~HYDRA_SDAT; 63 val |= HYDRA_SDAT_OE; 64 } 65 pdregw(data, val); 66} 67 68static int hydra_bit_getscl(void *data) 69{ 70 return (pdregr(data) & HYDRA_SCLK) != 0; 71} 72 73static int hydra_bit_getsda(void *data) 74{ 75 return (pdregr(data) & HYDRA_SDAT) != 0; 76} 77 78/* ------------------------------------------------------------------------ */ 79 80static struct i2c_algo_bit_data hydra_bit_data = { 81 .setsda = hydra_bit_setsda, 82 .setscl = hydra_bit_setscl, 83 .getsda = hydra_bit_getsda, 84 .getscl = hydra_bit_getscl, 85 .udelay = 5, 86 .timeout = HZ 87}; 88 89static struct i2c_adapter hydra_adap = { 90 .owner = THIS_MODULE, 91 .name = "Hydra i2c", 92 .algo_data = &hydra_bit_data, 93}; 94 95static const struct pci_device_id hydra_ids[] = { 96 { PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_HYDRA) }, 97 { 0, } 98}; 99 100MODULE_DEVICE_TABLE (pci, hydra_ids); 101 102static int hydra_probe(struct pci_dev *dev, 103 const struct pci_device_id *id) 104{ 105 unsigned long base = pci_resource_start(dev, 0); 106 int res; 107 108 if (!request_mem_region(base+offsetof(struct Hydra, CachePD), 4, 109 hydra_adap.name)) 110 return -EBUSY; 111 112 hydra_bit_data.data = pci_ioremap_bar(dev, 0); 113 if (hydra_bit_data.data == NULL) { 114 release_mem_region(base+offsetof(struct Hydra, CachePD), 4); 115 return -ENODEV; 116 } 117 118 pdregw(hydra_bit_data.data, 0); /* clear SCLK_OE and SDAT_OE */ 119 hydra_adap.dev.parent = &dev->dev; 120 res = i2c_bit_add_bus(&hydra_adap); 121 if (res < 0) { 122 iounmap(hydra_bit_data.data); 123 release_mem_region(base+offsetof(struct Hydra, CachePD), 4); 124 return res; 125 } 126 return 0; 127} 128 129static void hydra_remove(struct pci_dev *dev) 130{ 131 pdregw(hydra_bit_data.data, 0); /* clear SCLK_OE and SDAT_OE */ 132 i2c_del_adapter(&hydra_adap); 133 iounmap(hydra_bit_data.data); 134 release_mem_region(pci_resource_start(dev, 0)+ 135 offsetof(struct Hydra, CachePD), 4); 136} 137 138 139static struct pci_driver hydra_driver = { 140 .name = "hydra_smbus", 141 .id_table = hydra_ids, 142 .probe = hydra_probe, 143 .remove = hydra_remove, 144}; 145 146module_pci_driver(hydra_driver); 147 148MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>"); 149MODULE_DESCRIPTION("i2c for Apple Hydra Mac I/O"); 150MODULE_LICENSE("GPL");