i2c.c (3956B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Helper module for board specific I2C bus registration 4 * 5 * Copyright (C) 2009 Nokia Corporation. 6 */ 7 8#include <linux/i2c.h> 9#include <linux/platform_data/i2c-omap.h> 10 11#include "mux.h" 12#include "soc.h" 13#include "i2c.h" 14 15#define OMAP_I2C_SIZE 0x3f 16#define OMAP1_I2C_BASE 0xfffb3800 17 18static const char name[] = "omap_i2c"; 19 20static struct resource i2c_resources[2] = { 21}; 22 23static struct platform_device omap_i2c_devices[1] = { 24}; 25 26static void __init omap1_i2c_mux_pins(int bus_id) 27{ 28 if (cpu_is_omap7xx()) { 29 omap_cfg_reg(I2C_7XX_SDA); 30 omap_cfg_reg(I2C_7XX_SCL); 31 } else { 32 omap_cfg_reg(I2C_SDA); 33 omap_cfg_reg(I2C_SCL); 34 } 35} 36 37int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *pdata, 38 int bus_id) 39{ 40 struct platform_device *pdev; 41 struct resource *res; 42 43 if (bus_id > 1) 44 return -EINVAL; 45 46 omap1_i2c_mux_pins(bus_id); 47 48 pdev = &omap_i2c_devices[bus_id - 1]; 49 pdev->id = bus_id; 50 pdev->name = name; 51 pdev->num_resources = ARRAY_SIZE(i2c_resources); 52 res = i2c_resources; 53 res[0].start = OMAP1_I2C_BASE; 54 res[0].end = res[0].start + OMAP_I2C_SIZE; 55 res[0].flags = IORESOURCE_MEM; 56 res[1].start = INT_I2C; 57 res[1].flags = IORESOURCE_IRQ; 58 pdev->resource = res; 59 60 /* all OMAP1 have IP version 1 register set */ 61 pdata->rev = OMAP_I2C_IP_VERSION_1; 62 63 /* all OMAP1 I2C are implemented like this */ 64 pdata->flags = OMAP_I2C_FLAG_NO_FIFO | 65 OMAP_I2C_FLAG_SIMPLE_CLOCK | 66 OMAP_I2C_FLAG_16BIT_DATA_REG | 67 OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK; 68 69 /* how the cpu bus is wired up differs for 7xx only */ 70 71 if (cpu_is_omap7xx()) 72 pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_1; 73 else 74 pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_2; 75 76 pdev->dev.platform_data = pdata; 77 78 return platform_device_register(pdev); 79} 80 81#define OMAP_I2C_MAX_CONTROLLERS 4 82static struct omap_i2c_bus_platform_data i2c_pdata[OMAP_I2C_MAX_CONTROLLERS]; 83 84#define OMAP_I2C_CMDLINE_SETUP (BIT(31)) 85 86/** 87 * omap_i2c_bus_setup - Process command line options for the I2C bus speed 88 * @str: String of options 89 * 90 * This function allow to override the default I2C bus speed for given I2C 91 * bus with a command line option. 92 * 93 * Format: i2c_bus=bus_id,clkrate (in kHz) 94 * 95 * Returns 1 on success, 0 otherwise. 96 */ 97static int __init omap_i2c_bus_setup(char *str) 98{ 99 int ints[3]; 100 101 get_options(str, 3, ints); 102 if (ints[0] < 2 || ints[1] < 1 || 103 ints[1] > OMAP_I2C_MAX_CONTROLLERS) 104 return 0; 105 i2c_pdata[ints[1] - 1].clkrate = ints[2]; 106 i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP; 107 108 return 1; 109} 110__setup("i2c_bus=", omap_i2c_bus_setup); 111 112/* 113 * Register busses defined in command line but that are not registered with 114 * omap_register_i2c_bus from board initialization code. 115 */ 116int __init omap_register_i2c_bus_cmdline(void) 117{ 118 int i, err = 0; 119 120 for (i = 0; i < ARRAY_SIZE(i2c_pdata); i++) 121 if (i2c_pdata[i].clkrate & OMAP_I2C_CMDLINE_SETUP) { 122 i2c_pdata[i].clkrate &= ~OMAP_I2C_CMDLINE_SETUP; 123 err = omap_i2c_add_bus(&i2c_pdata[i], i + 1); 124 if (err) 125 goto out; 126 } 127 128out: 129 return err; 130} 131 132/** 133 * omap_register_i2c_bus - register I2C bus with device descriptors 134 * @bus_id: bus id counting from number 1 135 * @clkrate: clock rate of the bus in kHz 136 * @info: pointer into I2C device descriptor table or NULL 137 * @len: number of descriptors in the table 138 * 139 * Returns 0 on success or an error code. 140 */ 141int __init omap_register_i2c_bus(int bus_id, u32 clkrate, 142 struct i2c_board_info const *info, 143 unsigned len) 144{ 145 int err; 146 147 BUG_ON(bus_id < 1 || bus_id > OMAP_I2C_MAX_CONTROLLERS); 148 149 if (info) { 150 err = i2c_register_board_info(bus_id, info, len); 151 if (err) 152 return err; 153 } 154 155 if (!i2c_pdata[bus_id - 1].clkrate) 156 i2c_pdata[bus_id - 1].clkrate = clkrate; 157 158 i2c_pdata[bus_id - 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP; 159 160 return omap_i2c_add_bus(&i2c_pdata[bus_id - 1], bus_id); 161} 162 163static int __init omap_i2c_cmdline(void) 164{ 165 return omap_register_i2c_bus_cmdline(); 166} 167subsys_initcall(omap_i2c_cmdline);