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