1*500d9e35Sjmcneill /* $NetBSD: cdnsiic_fdt.c,v 1.1 2022/11/05 17:31:37 jmcneill Exp $ */
2*500d9e35Sjmcneill
3*500d9e35Sjmcneill /*-
4*500d9e35Sjmcneill * Copyright (c) 2022 Jared McNeill <jmcneill@invisible.ca>
5*500d9e35Sjmcneill * All rights reserved.
6*500d9e35Sjmcneill *
7*500d9e35Sjmcneill * Redistribution and use in source and binary forms, with or without
8*500d9e35Sjmcneill * modification, are permitted provided that the following conditions
9*500d9e35Sjmcneill * are met:
10*500d9e35Sjmcneill * 1. Redistributions of source code must retain the above copyright
11*500d9e35Sjmcneill * notice, this list of conditions and the following disclaimer.
12*500d9e35Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright
13*500d9e35Sjmcneill * notice, this list of conditions and the following disclaimer in the
14*500d9e35Sjmcneill * documentation and/or other materials provided with the distribution.
15*500d9e35Sjmcneill *
16*500d9e35Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17*500d9e35Sjmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18*500d9e35Sjmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19*500d9e35Sjmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20*500d9e35Sjmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*500d9e35Sjmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*500d9e35Sjmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*500d9e35Sjmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*500d9e35Sjmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*500d9e35Sjmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*500d9e35Sjmcneill * POSSIBILITY OF SUCH DAMAGE.
27*500d9e35Sjmcneill */
28*500d9e35Sjmcneill
29*500d9e35Sjmcneill #include <sys/cdefs.h>
30*500d9e35Sjmcneill
31*500d9e35Sjmcneill __KERNEL_RCSID(0, "$NetBSD: cdnsiic_fdt.c,v 1.1 2022/11/05 17:31:37 jmcneill Exp $");
32*500d9e35Sjmcneill
33*500d9e35Sjmcneill #include <sys/param.h>
34*500d9e35Sjmcneill #include <sys/bus.h>
35*500d9e35Sjmcneill #include <sys/device.h>
36*500d9e35Sjmcneill #include <sys/intr.h>
37*500d9e35Sjmcneill #include <sys/systm.h>
38*500d9e35Sjmcneill #include <sys/time.h>
39*500d9e35Sjmcneill #include <sys/kmem.h>
40*500d9e35Sjmcneill
41*500d9e35Sjmcneill #include <dev/i2c/i2cvar.h>
42*500d9e35Sjmcneill
43*500d9e35Sjmcneill #include <dev/fdt/fdtvar.h>
44*500d9e35Sjmcneill #include <dev/ic/cdnsiicvar.h>
45*500d9e35Sjmcneill
46*500d9e35Sjmcneill static const struct device_compatible_entry compat_data[] = {
47*500d9e35Sjmcneill { .compat = "cdns,i2c-r1p10" },
48*500d9e35Sjmcneill { .compat = "cdns,i2c-r1p14" },
49*500d9e35Sjmcneill DEVICE_COMPAT_EOL
50*500d9e35Sjmcneill };
51*500d9e35Sjmcneill
52*500d9e35Sjmcneill static int
cdnsiic_fdt_match(device_t parent,cfdata_t cf,void * aux)53*500d9e35Sjmcneill cdnsiic_fdt_match(device_t parent, cfdata_t cf, void *aux)
54*500d9e35Sjmcneill {
55*500d9e35Sjmcneill struct fdt_attach_args * const faa = aux;
56*500d9e35Sjmcneill
57*500d9e35Sjmcneill return of_compatible_match(faa->faa_phandle, compat_data);
58*500d9e35Sjmcneill }
59*500d9e35Sjmcneill
60*500d9e35Sjmcneill static void
cdnsiic_fdt_attach(device_t parent,device_t self,void * aux)61*500d9e35Sjmcneill cdnsiic_fdt_attach(device_t parent, device_t self, void *aux)
62*500d9e35Sjmcneill {
63*500d9e35Sjmcneill struct cdnsiic_softc * const sc = device_private(self);
64*500d9e35Sjmcneill struct fdt_attach_args * const faa = aux;
65*500d9e35Sjmcneill const int phandle = faa->faa_phandle;
66*500d9e35Sjmcneill bus_addr_t addr;
67*500d9e35Sjmcneill bus_size_t size;
68*500d9e35Sjmcneill int error;
69*500d9e35Sjmcneill
70*500d9e35Sjmcneill if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
71*500d9e35Sjmcneill aprint_error(": couldn't get registers\n");
72*500d9e35Sjmcneill return;
73*500d9e35Sjmcneill }
74*500d9e35Sjmcneill
75*500d9e35Sjmcneill sc->sc_pclk = fdtbus_clock_get_index(phandle, 0);
76*500d9e35Sjmcneill if (sc->sc_pclk == NULL || clk_enable(sc->sc_pclk) != 0) {
77*500d9e35Sjmcneill aprint_error(": couldn't enable pclk\n");
78*500d9e35Sjmcneill return;
79*500d9e35Sjmcneill }
80*500d9e35Sjmcneill
81*500d9e35Sjmcneill if (of_getprop_uint32(phandle, "clock-frequency", &sc->sc_bus_freq))
82*500d9e35Sjmcneill sc->sc_bus_freq = 100000;
83*500d9e35Sjmcneill
84*500d9e35Sjmcneill sc->sc_dev = self;
85*500d9e35Sjmcneill sc->sc_bst = faa->faa_bst;
86*500d9e35Sjmcneill if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
87*500d9e35Sjmcneill aprint_error(": couldn't map registers\n");
88*500d9e35Sjmcneill return;
89*500d9e35Sjmcneill }
90*500d9e35Sjmcneill
91*500d9e35Sjmcneill error = cdnsiic_attach(sc);
92*500d9e35Sjmcneill if (error != 0) {
93*500d9e35Sjmcneill aprint_error_dev(self, "init failed, error = %d\n", error);
94*500d9e35Sjmcneill return;
95*500d9e35Sjmcneill }
96*500d9e35Sjmcneill
97*500d9e35Sjmcneill fdtbus_register_i2c_controller(&sc->sc_ic, phandle);
98*500d9e35Sjmcneill
99*500d9e35Sjmcneill fdtbus_attach_i2cbus(self, phandle, &sc->sc_ic, iicbus_print);
100*500d9e35Sjmcneill }
101*500d9e35Sjmcneill
102*500d9e35Sjmcneill CFATTACH_DECL_NEW(cdnsiic_fdt, sizeof(struct cdnsiic_softc),
103*500d9e35Sjmcneill cdnsiic_fdt_match, cdnsiic_fdt_attach, NULL, NULL);
104