12b27bdccSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2b63128e8STony Lindgren /*
3b63128e8STony Lindgren * Helper module for board specific I2C bus registration
4b63128e8STony Lindgren *
5b63128e8STony Lindgren * Copyright (C) 2009 Nokia Corporation.
6b63128e8STony Lindgren */
7b63128e8STony Lindgren
865fa3e71STony Lindgren #include <linux/i2c.h>
979fc540fSWolfram Sang #include <linux/platform_data/i2c-omap.h>
107e0a9e62SArnd Bergmann
117e0a9e62SArnd Bergmann #include "mux.h"
12e4c060dbSTony Lindgren #include "soc.h"
13*e514f1fdSArnd Bergmann #include "i2c.h"
14b63128e8STony Lindgren
153a8761c0STony Lindgren #define OMAP_I2C_SIZE 0x3f
163a8761c0STony Lindgren #define OMAP1_I2C_BASE 0xfffb3800
173a8761c0STony Lindgren
183a8761c0STony Lindgren static const char name[] = "omap_i2c";
193a8761c0STony Lindgren
203a8761c0STony Lindgren static struct resource i2c_resources[2] = {
213a8761c0STony Lindgren };
223a8761c0STony Lindgren
233a8761c0STony Lindgren static struct platform_device omap_i2c_devices[1] = {
243a8761c0STony Lindgren };
253a8761c0STony Lindgren
omap1_i2c_mux_pins(int bus_id)263a8761c0STony Lindgren static void __init omap1_i2c_mux_pins(int bus_id)
27b63128e8STony Lindgren {
28b63128e8STony Lindgren omap_cfg_reg(I2C_SDA);
29b63128e8STony Lindgren omap_cfg_reg(I2C_SCL);
30bf92a407SCory Maccarrone }
313a8761c0STony Lindgren
omap_i2c_add_bus(struct omap_i2c_bus_platform_data * pdata,int bus_id)323a8761c0STony Lindgren int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *pdata,
333a8761c0STony Lindgren int bus_id)
343a8761c0STony Lindgren {
353a8761c0STony Lindgren struct platform_device *pdev;
363a8761c0STony Lindgren struct resource *res;
373a8761c0STony Lindgren
38c34f7c69STony Lindgren if (bus_id > 1)
39c34f7c69STony Lindgren return -EINVAL;
40c34f7c69STony Lindgren
413a8761c0STony Lindgren omap1_i2c_mux_pins(bus_id);
423a8761c0STony Lindgren
433a8761c0STony Lindgren pdev = &omap_i2c_devices[bus_id - 1];
443a8761c0STony Lindgren pdev->id = bus_id;
453a8761c0STony Lindgren pdev->name = name;
463a8761c0STony Lindgren pdev->num_resources = ARRAY_SIZE(i2c_resources);
473a8761c0STony Lindgren res = i2c_resources;
483a8761c0STony Lindgren res[0].start = OMAP1_I2C_BASE;
493a8761c0STony Lindgren res[0].end = res[0].start + OMAP_I2C_SIZE;
503a8761c0STony Lindgren res[0].flags = IORESOURCE_MEM;
51685e2d08STony Lindgren res[1].start = INT_I2C;
523a8761c0STony Lindgren res[1].flags = IORESOURCE_IRQ;
533a8761c0STony Lindgren pdev->resource = res;
543a8761c0STony Lindgren
553a8761c0STony Lindgren /* all OMAP1 have IP version 1 register set */
563a8761c0STony Lindgren pdata->rev = OMAP_I2C_IP_VERSION_1;
573a8761c0STony Lindgren
583a8761c0STony Lindgren /* all OMAP1 I2C are implemented like this */
593a8761c0STony Lindgren pdata->flags = OMAP_I2C_FLAG_NO_FIFO |
603a8761c0STony Lindgren OMAP_I2C_FLAG_SIMPLE_CLOCK |
613a8761c0STony Lindgren OMAP_I2C_FLAG_16BIT_DATA_REG |
623a8761c0STony Lindgren OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK;
633a8761c0STony Lindgren
643a8761c0STony Lindgren /* how the cpu bus is wired up differs for 7xx only */
653a8761c0STony Lindgren
663a8761c0STony Lindgren pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_2;
673a8761c0STony Lindgren
683a8761c0STony Lindgren pdev->dev.platform_data = pdata;
693a8761c0STony Lindgren
703a8761c0STony Lindgren return platform_device_register(pdev);
713a8761c0STony Lindgren }
72a6cf912cSTony Lindgren
7365fa3e71STony Lindgren #define OMAP_I2C_MAX_CONTROLLERS 4
7465fa3e71STony Lindgren static struct omap_i2c_bus_platform_data i2c_pdata[OMAP_I2C_MAX_CONTROLLERS];
7565fa3e71STony Lindgren
7665fa3e71STony Lindgren #define OMAP_I2C_CMDLINE_SETUP (BIT(31))
7765fa3e71STony Lindgren
7865fa3e71STony Lindgren /**
7965fa3e71STony Lindgren * omap_i2c_bus_setup - Process command line options for the I2C bus speed
8065fa3e71STony Lindgren * @str: String of options
8165fa3e71STony Lindgren *
8265fa3e71STony Lindgren * This function allow to override the default I2C bus speed for given I2C
8365fa3e71STony Lindgren * bus with a command line option.
8465fa3e71STony Lindgren *
8565fa3e71STony Lindgren * Format: i2c_bus=bus_id,clkrate (in kHz)
8665fa3e71STony Lindgren *
8765fa3e71STony Lindgren * Returns 1 on success, 0 otherwise.
8865fa3e71STony Lindgren */
omap_i2c_bus_setup(char * str)8965fa3e71STony Lindgren static int __init omap_i2c_bus_setup(char *str)
9065fa3e71STony Lindgren {
9165fa3e71STony Lindgren int ints[3];
9265fa3e71STony Lindgren
9365fa3e71STony Lindgren get_options(str, 3, ints);
9465fa3e71STony Lindgren if (ints[0] < 2 || ints[1] < 1 ||
9565fa3e71STony Lindgren ints[1] > OMAP_I2C_MAX_CONTROLLERS)
9665fa3e71STony Lindgren return 0;
9765fa3e71STony Lindgren i2c_pdata[ints[1] - 1].clkrate = ints[2];
9865fa3e71STony Lindgren i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP;
9965fa3e71STony Lindgren
10065fa3e71STony Lindgren return 1;
10165fa3e71STony Lindgren }
10265fa3e71STony Lindgren __setup("i2c_bus=", omap_i2c_bus_setup);
10365fa3e71STony Lindgren
10465fa3e71STony Lindgren /*
10565fa3e71STony Lindgren * Register busses defined in command line but that are not registered with
10665fa3e71STony Lindgren * omap_register_i2c_bus from board initialization code.
10765fa3e71STony Lindgren */
omap_register_i2c_bus_cmdline(void)10865fa3e71STony Lindgren int __init omap_register_i2c_bus_cmdline(void)
10965fa3e71STony Lindgren {
11065fa3e71STony Lindgren int i, err = 0;
11165fa3e71STony Lindgren
11265fa3e71STony Lindgren for (i = 0; i < ARRAY_SIZE(i2c_pdata); i++)
11365fa3e71STony Lindgren if (i2c_pdata[i].clkrate & OMAP_I2C_CMDLINE_SETUP) {
11465fa3e71STony Lindgren i2c_pdata[i].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;
11565fa3e71STony Lindgren err = omap_i2c_add_bus(&i2c_pdata[i], i + 1);
11665fa3e71STony Lindgren if (err)
11765fa3e71STony Lindgren goto out;
11865fa3e71STony Lindgren }
11965fa3e71STony Lindgren
12065fa3e71STony Lindgren out:
12165fa3e71STony Lindgren return err;
12265fa3e71STony Lindgren }
12365fa3e71STony Lindgren
12465fa3e71STony Lindgren /**
12565fa3e71STony Lindgren * omap_register_i2c_bus - register I2C bus with device descriptors
12665fa3e71STony Lindgren * @bus_id: bus id counting from number 1
12765fa3e71STony Lindgren * @clkrate: clock rate of the bus in kHz
12865fa3e71STony Lindgren * @info: pointer into I2C device descriptor table or NULL
12965fa3e71STony Lindgren * @len: number of descriptors in the table
13065fa3e71STony Lindgren *
13165fa3e71STony Lindgren * Returns 0 on success or an error code.
13265fa3e71STony Lindgren */
omap_register_i2c_bus(int bus_id,u32 clkrate,struct i2c_board_info const * info,unsigned len)13365fa3e71STony Lindgren int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
13465fa3e71STony Lindgren struct i2c_board_info const *info,
13565fa3e71STony Lindgren unsigned len)
13665fa3e71STony Lindgren {
13765fa3e71STony Lindgren int err;
13865fa3e71STony Lindgren
13965fa3e71STony Lindgren BUG_ON(bus_id < 1 || bus_id > OMAP_I2C_MAX_CONTROLLERS);
14065fa3e71STony Lindgren
14165fa3e71STony Lindgren if (info) {
14265fa3e71STony Lindgren err = i2c_register_board_info(bus_id, info, len);
14365fa3e71STony Lindgren if (err)
14465fa3e71STony Lindgren return err;
14565fa3e71STony Lindgren }
14665fa3e71STony Lindgren
14765fa3e71STony Lindgren if (!i2c_pdata[bus_id - 1].clkrate)
14865fa3e71STony Lindgren i2c_pdata[bus_id - 1].clkrate = clkrate;
14965fa3e71STony Lindgren
15065fa3e71STony Lindgren i2c_pdata[bus_id - 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;
15165fa3e71STony Lindgren
15265fa3e71STony Lindgren return omap_i2c_add_bus(&i2c_pdata[bus_id - 1], bus_id);
15365fa3e71STony Lindgren }
15465fa3e71STony Lindgren
omap_i2c_cmdline(void)155a6cf912cSTony Lindgren static int __init omap_i2c_cmdline(void)
156a6cf912cSTony Lindgren {
157a6cf912cSTony Lindgren return omap_register_i2c_bus_cmdline();
158a6cf912cSTony Lindgren }
159a6cf912cSTony Lindgren subsys_initcall(omap_i2c_cmdline);
160