Skip to content

Commit b3f489b

Browse files
Lukasz MajewskiFelipe Balbi
authored andcommitted
usb:hsotg:samsung: Determine number of EPs from HW configuration register
This commit adds support for determining of EPs number during run time. Configuration is read from a HW configuration register in a specially created s3c_hsotg_hw_cfg function. Moreover it was necessary to defer at probe allocation of the struct s3c_hsotg_ep instances until number of endpoints is known. Signed-off-by: Lukasz Majewski <[email protected]> Signed-off-by: Kyungmin Park <[email protected]> Signed-off-by: Felipe Balbi <[email protected]>
1 parent 12a1f4d commit b3f489b

File tree

1 file changed

+100
-67
lines changed

1 file changed

+100
-67
lines changed

drivers/usb/gadget/s3c-hsotg.c

Lines changed: 100 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,6 @@ struct s3c_hsotg_ep {
128128
char name[10];
129129
};
130130

131-
#define S3C_HSOTG_EPS (8+1) /* limit to 9 for the moment */
132-
133131
/**
134132
* struct s3c_hsotg - driver state.
135133
* @dev: The parent device supplied to the probe function
@@ -140,6 +138,7 @@ struct s3c_hsotg_ep {
140138
* @irq: The IRQ number we are using
141139
* @supplies: Definition of USB power supplies
142140
* @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
141+
* @num_of_eps: Number of available EPs (excluding EP0)
143142
* @debug_root: root directrory for debugfs.
144143
* @debug_file: main status file for debugfs.
145144
* @debug_fifo: FIFO status file for debugfs.
@@ -164,6 +163,7 @@ struct s3c_hsotg {
164163
struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)];
165164

166165
unsigned int dedicated_fifos:1;
166+
unsigned char num_of_eps;
167167

168168
struct dentry *debug_root;
169169
struct dentry *debug_file;
@@ -177,7 +177,7 @@ struct s3c_hsotg {
177177
struct usb_gadget gadget;
178178
unsigned int setup;
179179
unsigned long last_rst;
180-
struct s3c_hsotg_ep eps[];
180+
struct s3c_hsotg_ep *eps;
181181
};
182182

183183
/**
@@ -952,7 +952,7 @@ static struct s3c_hsotg_ep *ep_from_windex(struct s3c_hsotg *hsotg,
952952
if (windex >= 0x100)
953953
return NULL;
954954

955-
if (idx > S3C_HSOTG_EPS)
955+
if (idx > hsotg->num_of_eps)
956956
return NULL;
957957

958958
if (idx && ep->dir_in != dir)
@@ -2036,7 +2036,7 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg)
20362036
if (ep0_mps) {
20372037
int i;
20382038
s3c_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps);
2039-
for (i = 1; i < S3C_HSOTG_EPS; i++)
2039+
for (i = 1; i < hsotg->num_of_eps; i++)
20402040
s3c_hsotg_set_ep_maxpacket(hsotg, i, ep_mps);
20412041
}
20422042

@@ -2099,7 +2099,7 @@ static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg)
20992099
{
21002100
unsigned ep;
21012101

2102-
for (ep = 0; ep < S3C_HSOTG_EPS; ep++)
2102+
for (ep = 0; ep < hsotg->num_of_eps; ep++)
21032103
kill_all_requests(hsotg, &hsotg->eps[ep], -ESHUTDOWN, true);
21042104

21052105
call_gadget(hsotg, disconnect);
@@ -2117,7 +2117,7 @@ static void s3c_hsotg_irq_fifoempty(struct s3c_hsotg *hsotg, bool periodic)
21172117

21182118
/* look through for any more data to transmit */
21192119

2120-
for (epno = 0; epno < S3C_HSOTG_EPS; epno++) {
2120+
for (epno = 0; epno < hsotg->num_of_eps; epno++) {
21212121
ep = &hsotg->eps[epno];
21222122

21232123
if (!ep->dir_in)
@@ -2783,6 +2783,45 @@ static void s3c_hsotg_phy_disable(struct s3c_hsotg *hsotg)
27832783
hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
27842784
}
27852785

2786+
static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
2787+
{
2788+
/* unmask subset of endpoint interrupts */
2789+
2790+
writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk |
2791+
S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk,
2792+
hsotg->regs + S3C_DIEPMSK);
2793+
2794+
writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk |
2795+
S3C_DOEPMSK_EPDisbldMsk | S3C_DOEPMSK_XferComplMsk,
2796+
hsotg->regs + S3C_DOEPMSK);
2797+
2798+
writel(0, hsotg->regs + S3C_DAINTMSK);
2799+
2800+
/* Be in disconnected state until gadget is registered */
2801+
__orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
2802+
2803+
if (0) {
2804+
/* post global nak until we're ready */
2805+
writel(S3C_DCTL_SGNPInNAK | S3C_DCTL_SGOUTNak,
2806+
hsotg->regs + S3C_DCTL);
2807+
}
2808+
2809+
/* setup fifos */
2810+
2811+
dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
2812+
readl(hsotg->regs + S3C_GRXFSIZ),
2813+
readl(hsotg->regs + S3C_GNPTXFSIZ));
2814+
2815+
s3c_hsotg_init_fifo(hsotg);
2816+
2817+
/* set the PLL on, remove the HNP/SRP and set the PHY */
2818+
writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) | (0x5 << 10),
2819+
hsotg->regs + S3C_GUSBCFG);
2820+
2821+
writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0,
2822+
hsotg->regs + S3C_GAHBCFG);
2823+
}
2824+
27862825
static int s3c_hsotg_start(struct usb_gadget_driver *driver,
27872826
int (*bind)(struct usb_gadget *))
27882827
{
@@ -2853,7 +2892,7 @@ static int s3c_hsotg_stop(struct usb_gadget_driver *driver)
28532892
return -EINVAL;
28542893

28552894
/* all endpoints should be shutdown */
2856-
for (ep = 0; ep < S3C_HSOTG_EPS; ep++)
2895+
for (ep = 0; ep < hsotg->num_of_eps; ep++)
28572896
s3c_hsotg_ep_disable(&hsotg->eps[ep].ep);
28582897

28592898
call_gadget(hsotg, disconnect);
@@ -2944,53 +2983,28 @@ static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg,
29442983
}
29452984
}
29462985

2947-
static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
2986+
/**
2987+
* s3c_hsotg_hw_cfg - read HW configuration registers
2988+
* @param: The device state
2989+
*
2990+
* Read the USB core HW configuration registers
2991+
*/
2992+
static void s3c_hsotg_hw_cfg(struct s3c_hsotg *hsotg)
29482993
{
2949-
u32 cfg4;
2950-
2951-
/* unmask subset of endpoint interrupts */
2952-
2953-
writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk |
2954-
S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk,
2955-
hsotg->regs + S3C_DIEPMSK);
2956-
2957-
writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk |
2958-
S3C_DOEPMSK_EPDisbldMsk | S3C_DOEPMSK_XferComplMsk,
2959-
hsotg->regs + S3C_DOEPMSK);
2960-
2961-
writel(0, hsotg->regs + S3C_DAINTMSK);
2962-
2963-
/* Be in disconnected state until gadget is registered */
2964-
__orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
2965-
2966-
if (0) {
2967-
/* post global nak until we're ready */
2968-
writel(S3C_DCTL_SGNPInNAK | S3C_DCTL_SGOUTNak,
2969-
hsotg->regs + S3C_DCTL);
2970-
}
2971-
2972-
/* setup fifos */
2973-
2974-
dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
2975-
readl(hsotg->regs + S3C_GRXFSIZ),
2976-
readl(hsotg->regs + S3C_GNPTXFSIZ));
2977-
2978-
s3c_hsotg_init_fifo(hsotg);
2979-
2980-
/* set the PLL on, remove the HNP/SRP and set the PHY */
2981-
writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) | (0x5 << 10),
2982-
hsotg->regs + S3C_GUSBCFG);
2994+
u32 cfg2, cfg4;
2995+
/* check hardware configuration */
29832996

2984-
writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0,
2985-
hsotg->regs + S3C_GAHBCFG);
2997+
cfg2 = readl(hsotg->regs + 0x48);
2998+
hsotg->num_of_eps = (cfg2 >> 10) & 0xF;
29862999

2987-
/* check hardware configuration */
3000+
dev_info(hsotg->dev, "EPs:%d\n", hsotg->num_of_eps);
29883001

29893002
cfg4 = readl(hsotg->regs + 0x50);
29903003
hsotg->dedicated_fifos = (cfg4 >> 25) & 1;
29913004

29923005
dev_info(hsotg->dev, "%s fifos\n",
29933006
hsotg->dedicated_fifos ? "dedicated" : "shared");
3007+
29943008
}
29953009

29963010
static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)
@@ -3284,7 +3298,7 @@ static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
32843298

32853299
/* create one file for each endpoint */
32863300

3287-
for (epidx = 0; epidx < S3C_HSOTG_EPS; epidx++) {
3301+
for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) {
32883302
struct s3c_hsotg_ep *ep = &hsotg->eps[epidx];
32893303

32903304
ep->debugfs = debugfs_create_file(ep->name, 0444,
@@ -3306,7 +3320,7 @@ static void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
33063320
{
33073321
unsigned epidx;
33083322

3309-
for (epidx = 0; epidx < S3C_HSOTG_EPS; epidx++) {
3323+
for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) {
33103324
struct s3c_hsotg_ep *ep = &hsotg->eps[epidx];
33113325
debugfs_remove(ep->debugfs);
33123326
}
@@ -3320,6 +3334,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
33203334
{
33213335
struct s3c_hsotg_plat *plat = pdev->dev.platform_data;
33223336
struct device *dev = &pdev->dev;
3337+
struct s3c_hsotg_ep *eps;
33233338
struct s3c_hsotg *hsotg;
33243339
struct resource *res;
33253340
int epnum;
@@ -3332,9 +3347,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
33323347
return -EINVAL;
33333348
}
33343349

3335-
hsotg = kzalloc(sizeof(struct s3c_hsotg) +
3336-
sizeof(struct s3c_hsotg_ep) * S3C_HSOTG_EPS,
3337-
GFP_KERNEL);
3350+
hsotg = kzalloc(sizeof(struct s3c_hsotg), GFP_KERNEL);
33383351
if (!hsotg) {
33393352
dev_err(dev, "cannot get memory\n");
33403353
return -ENOMEM;
@@ -3401,20 +3414,6 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
34013414
hsotg->gadget.dev.parent = dev;
34023415
hsotg->gadget.dev.dma_mask = dev->dma_mask;
34033416

3404-
/* setup endpoint information */
3405-
3406-
INIT_LIST_HEAD(&hsotg->gadget.ep_list);
3407-
hsotg->gadget.ep0 = &hsotg->eps[0].ep;
3408-
3409-
/* allocate EP0 request */
3410-
3411-
hsotg->ctrl_req = s3c_hsotg_ep_alloc_request(&hsotg->eps[0].ep,
3412-
GFP_KERNEL);
3413-
if (!hsotg->ctrl_req) {
3414-
dev_err(dev, "failed to allocate ctrl req\n");
3415-
goto err_regs;
3416-
}
3417-
34183417
/* reset the system */
34193418

34203419
clk_enable(hsotg->clk);
@@ -3444,14 +3443,45 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
34443443

34453444
s3c_hsotg_corereset(hsotg);
34463445
s3c_hsotg_init(hsotg);
3446+
s3c_hsotg_hw_cfg(hsotg);
3447+
3448+
/* hsotg->num_of_eps holds number of EPs other than ep0 */
3449+
3450+
if (hsotg->num_of_eps == 0) {
3451+
dev_err(dev, "wrong number of EPs (zero)\n");
3452+
goto err_supplies;
3453+
}
3454+
3455+
eps = kcalloc(hsotg->num_of_eps + 1, sizeof(struct s3c_hsotg_ep),
3456+
GFP_KERNEL);
3457+
if (!eps) {
3458+
dev_err(dev, "cannot get memory\n");
3459+
goto err_supplies;
3460+
}
3461+
3462+
hsotg->eps = eps;
3463+
3464+
/* setup endpoint information */
3465+
3466+
INIT_LIST_HEAD(&hsotg->gadget.ep_list);
3467+
hsotg->gadget.ep0 = &hsotg->eps[0].ep;
3468+
3469+
/* allocate EP0 request */
3470+
3471+
hsotg->ctrl_req = s3c_hsotg_ep_alloc_request(&hsotg->eps[0].ep,
3472+
GFP_KERNEL);
3473+
if (!hsotg->ctrl_req) {
3474+
dev_err(dev, "failed to allocate ctrl req\n");
3475+
goto err_ep_mem;
3476+
}
34473477

34483478
/* initialise the endpoints now the core has been initialised */
3449-
for (epnum = 0; epnum < S3C_HSOTG_EPS; epnum++)
3479+
for (epnum = 0; epnum < hsotg->num_of_eps; epnum++)
34503480
s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum);
34513481

34523482
ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
34533483
if (ret)
3454-
goto err_supplies;
3484+
goto err_ep_mem;
34553485

34563486
s3c_hsotg_create_debug(hsotg);
34573487

@@ -3460,6 +3490,9 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
34603490
our_hsotg = hsotg;
34613491
return 0;
34623492

3493+
err_ep_mem:
3494+
kfree(eps);
3495+
34633496
err_supplies:
34643497
s3c_hsotg_phy_disable(hsotg);
34653498

0 commit comments

Comments
 (0)