-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable I2C#6 instead of I2C#8 #12
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Copyright (c) 2018 Emlid Limited | ||
*/ | ||
|
||
#include <common.h> | ||
#include <dm.h> | ||
#include <regmap.h> | ||
#include <syscon.h> | ||
#include <asm/cpu.h> | ||
#include <asm/scu.h> | ||
#include <linux/io.h> | ||
|
||
#define BUFCFG_OFFSET 0x100 | ||
|
||
#define MRFLD_FAMILY_LEN 0x400 | ||
|
||
#define pin_to_bufno(f, p) ((p) - (f)->pin_base) | ||
|
||
struct mrfld_family { | ||
unsigned int family_number; | ||
unsigned int pin_base; | ||
size_t npins; | ||
void __iomem *regs; | ||
}; | ||
|
||
#define MRFLD_FAMILY(b, s, e) \ | ||
{ \ | ||
.family_number = (b), \ | ||
.pin_base = (s), \ | ||
.npins = (e) - (s) + 1, \ | ||
} | ||
|
||
static struct mrfld_family mrfld_families[] = { | ||
MRFLD_FAMILY(7, 101, 114), | ||
}; | ||
|
||
struct mrfld_pinctrl { | ||
const struct mrfld_family *families; | ||
size_t nfamilies; | ||
}; | ||
|
||
static const struct mrfld_family * | ||
mrfld_get_family(struct mrfld_pinctrl *mp, unsigned int pin) | ||
{ | ||
const struct mrfld_family *family; | ||
unsigned int i; | ||
|
||
for (i = 0; i < mp->nfamilies; i++) { | ||
family = &mp->families[i]; | ||
if (pin >= family->pin_base && | ||
pin < family->pin_base + family->npins) | ||
return family; | ||
} | ||
|
||
printf("failed to find family for pin %u\n", pin); | ||
return NULL; | ||
} | ||
|
||
static void __iomem * | ||
mrfld_get_bufcfg(struct mrfld_pinctrl *pinctrl, unsigned int pin) | ||
{ | ||
const struct mrfld_family *family; | ||
unsigned int bufno; | ||
|
||
family = mrfld_get_family(pinctrl, pin); | ||
if (!family) | ||
return NULL; | ||
|
||
bufno = pin_to_bufno(family, pin); | ||
|
||
return family->regs + BUFCFG_OFFSET + bufno * 4; | ||
} | ||
|
||
static void | ||
mrfld_setup_families(void *base_addr, struct mrfld_family *families, unsigned int nfam) | ||
{ | ||
for (int i = 0; i < nfam; i++) { | ||
struct mrfld_family *family = &families[i]; | ||
|
||
family->regs = base_addr + family->family_number * MRFLD_FAMILY_LEN; | ||
} | ||
} | ||
|
||
int mrfld_pinconfig_protected(unsigned int pin, u32 mask, u32 bits) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this is an API it has to get a pin control device first, something like
The idea behind is to get lazy probe (that's called "Driver Model" in U-Boot). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @andy-shev But it seems like probe is already automagically called just by the sheer addition of the probe callback, doesn't it? I'm pretty sure I'm missing something, of course. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you call function before device is probed, it wouldn't work and crash everything. ->probe() will be called when we try to get pointer to a device. |
||
{ | ||
struct mrfld_pinctrl *pinctrl; | ||
struct udevice *dev; | ||
void __iomem *bufcfg; | ||
u32 v, value; | ||
int ret; | ||
|
||
ret = syscon_get_by_driver_data(X86_SYSCON_PINCONF, &dev); | ||
if (ret) | ||
return ret; | ||
|
||
pinctrl = dev_get_priv(dev); | ||
|
||
bufcfg = mrfld_get_bufcfg(pinctrl, pin); | ||
if (!bufcfg) | ||
return -EINVAL; | ||
|
||
value = readl(bufcfg); | ||
|
||
v = (value & ~mask) | (bits & mask); | ||
|
||
debug("scu: v: 0x%x p: 0x%x bits: %d, mask: %d bufcfg: 0x%p\n", | ||
v, (u32)bufcfg, bits, mask, bufcfg); | ||
|
||
ret = scu_ipc_raw_command(IPCMSG_INDIRECT_WRITE, 0, &v, 4, | ||
NULL, 0, (u32)bufcfg, 0); | ||
if (ret) | ||
pr_err("Failed to set mode via SCU for pin %u (%d)\n", pin, ret); | ||
|
||
return ret; | ||
} | ||
|
||
static int tangier_pinctrl_probe(struct udevice *dev) | ||
{ | ||
void *base_addr = syscon_get_first_range(X86_SYSCON_PINCONF); | ||
|
||
struct mrfld_pinctrl *pinctrl = dev_get_priv(dev); | ||
|
||
mrfld_setup_families(base_addr, mrfld_families, | ||
ARRAY_SIZE(mrfld_families)); | ||
|
||
pinctrl->families = mrfld_families; | ||
pinctrl->nfamilies = ARRAY_SIZE(mrfld_families); | ||
|
||
return 0; | ||
} | ||
|
||
static const struct udevice_id tangier_pinctrl_match[] = { | ||
{ .compatible = "intel,pinctrl-tangier", .data = X86_SYSCON_PINCONF }, | ||
{ /* sentinel */ } | ||
}; | ||
|
||
U_BOOT_DRIVER(tangier_pinctrl) = { | ||
.name = "tangier_pinctrl", | ||
.id = UCLASS_SYSCON, | ||
.of_match = tangier_pinctrl_match, | ||
.probe = tangier_pinctrl_probe, | ||
.priv_auto_alloc_size = sizeof(struct mrfld_pinctrl), | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, like I said in the bug report, check pinctrl-sandbox.c for a hint how this should look like. (Yes, I understand that we are creating a limited driver, it needs to be taken into account)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. So we're making it the UCLASS_PINCTRL, then? With some of pinctrl_ops implemented? And then we'll configure the pins in edison.c using the pinctrl API? Is this the plan? If so, I'll need some time adapting this code to the pinctrl API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure that this what upstream ask us during review. However, we can try first with reduced solution. I guess, we may send it upstream and see what they will tell. In any case it would be nice to have your stuff in my tree sooner.